Statistics
| Branch: | Revision:

root / hw / input / ps2.c @ a8aec295

History | View | Annotate | Download (20.4 kB)

1 0e43e99c bellard
/*
2 0e43e99c bellard
 * QEMU PS/2 keyboard/mouse emulation
3 5fafdf24 ths
 *
4 0e43e99c bellard
 * Copyright (c) 2003 Fabrice Bellard
5 5fafdf24 ths
 *
6 0e43e99c bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 0e43e99c bellard
 * of this software and associated documentation files (the "Software"), to deal
8 0e43e99c bellard
 * in the Software without restriction, including without limitation the rights
9 0e43e99c bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 0e43e99c bellard
 * copies of the Software, and to permit persons to whom the Software is
11 0e43e99c bellard
 * furnished to do so, subject to the following conditions:
12 0e43e99c bellard
 *
13 0e43e99c bellard
 * The above copyright notice and this permission notice shall be included in
14 0e43e99c bellard
 * all copies or substantial portions of the Software.
15 0e43e99c bellard
 *
16 0e43e99c bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 0e43e99c bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 0e43e99c bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 0e43e99c bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 0e43e99c bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 0e43e99c bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 0e43e99c bellard
 * THE SOFTWARE.
23 0e43e99c bellard
 */
24 83c9f4ca Paolo Bonzini
#include "hw/hw.h"
25 0d09e41a Paolo Bonzini
#include "hw/input/ps2.h"
26 28ecbaee Paolo Bonzini
#include "ui/console.h"
27 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"
28 0e43e99c bellard
29 0e43e99c bellard
/* debug PC keyboard */
30 0e43e99c bellard
//#define DEBUG_KBD
31 0e43e99c bellard
32 0e43e99c bellard
/* debug PC keyboard : only mouse */
33 0e43e99c bellard
//#define DEBUG_MOUSE
34 0e43e99c bellard
35 0e43e99c bellard
/* Keyboard Commands */
36 0e43e99c bellard
#define KBD_CMD_SET_LEDS        0xED        /* Set keyboard leds */
37 0e43e99c bellard
#define KBD_CMD_ECHO             0xEE
38 e7d93956 aurel32
#define KBD_CMD_SCANCODE        0xF0        /* Get/set scancode set */
39 0e43e99c bellard
#define KBD_CMD_GET_ID                 0xF2        /* get keyboard ID */
40 0e43e99c bellard
#define KBD_CMD_SET_RATE        0xF3        /* Set typematic rate */
41 0e43e99c bellard
#define KBD_CMD_ENABLE                0xF4        /* Enable scanning */
42 0e43e99c bellard
#define KBD_CMD_RESET_DISABLE        0xF5        /* reset and disable scanning */
43 0e43e99c bellard
#define KBD_CMD_RESET_ENABLE           0xF6    /* reset and enable scanning */
44 0e43e99c bellard
#define KBD_CMD_RESET                0xFF        /* Reset */
45 0e43e99c bellard
46 0e43e99c bellard
/* Keyboard Replies */
47 0e43e99c bellard
#define KBD_REPLY_POR                0xAA        /* Power on reset */
48 35c4d671 aurel32
#define KBD_REPLY_ID                0xAB        /* Keyboard ID */
49 0e43e99c bellard
#define KBD_REPLY_ACK                0xFA        /* Command ACK */
50 0e43e99c bellard
#define KBD_REPLY_RESEND        0xFE        /* Command NACK, send the cmd again */
51 0e43e99c bellard
52 0e43e99c bellard
/* Mouse Commands */
53 0e43e99c bellard
#define AUX_SET_SCALE11                0xE6        /* Set 1:1 scaling */
54 0e43e99c bellard
#define AUX_SET_SCALE21                0xE7        /* Set 2:1 scaling */
55 0e43e99c bellard
#define AUX_SET_RES                0xE8        /* Set resolution */
56 0e43e99c bellard
#define AUX_GET_SCALE                0xE9        /* Get scaling factor */
57 0e43e99c bellard
#define AUX_SET_STREAM                0xEA        /* Set stream mode */
58 0e43e99c bellard
#define AUX_POLL                0xEB        /* Poll */
59 0e43e99c bellard
#define AUX_RESET_WRAP                0xEC        /* Reset wrap mode */
60 0e43e99c bellard
#define AUX_SET_WRAP                0xEE        /* Set wrap mode */
61 0e43e99c bellard
#define AUX_SET_REMOTE                0xF0        /* Set remote mode */
62 0e43e99c bellard
#define AUX_GET_TYPE                0xF2        /* Get type */
63 0e43e99c bellard
#define AUX_SET_SAMPLE                0xF3        /* Set sample rate */
64 0e43e99c bellard
#define AUX_ENABLE_DEV                0xF4        /* Enable aux device */
65 0e43e99c bellard
#define AUX_DISABLE_DEV                0xF5        /* Disable aux device */
66 0e43e99c bellard
#define AUX_SET_DEFAULT                0xF6
67 0e43e99c bellard
#define AUX_RESET                0xFF        /* Reset aux device */
68 0e43e99c bellard
#define AUX_ACK                        0xFA        /* Command byte ACK. */
69 0e43e99c bellard
70 0e43e99c bellard
#define MOUSE_STATUS_REMOTE     0x40
71 0e43e99c bellard
#define MOUSE_STATUS_ENABLED    0x20
72 0e43e99c bellard
#define MOUSE_STATUS_SCALE21    0x10
73 0e43e99c bellard
74 0e43e99c bellard
#define PS2_QUEUE_SIZE 256
75 0e43e99c bellard
76 0e43e99c bellard
typedef struct {
77 0e43e99c bellard
    uint8_t data[PS2_QUEUE_SIZE];
78 0e43e99c bellard
    int rptr, wptr, count;
79 0e43e99c bellard
} PS2Queue;
80 0e43e99c bellard
81 0e43e99c bellard
typedef struct {
82 0e43e99c bellard
    PS2Queue queue;
83 0e43e99c bellard
    int32_t write_cmd;
84 0e43e99c bellard
    void (*update_irq)(void *, int);
85 0e43e99c bellard
    void *update_arg;
86 0e43e99c bellard
} PS2State;
87 0e43e99c bellard
88 0e43e99c bellard
typedef struct {
89 0e43e99c bellard
    PS2State common;
90 0e43e99c bellard
    int scan_enabled;
91 5cbdb3a3 Stefan Weil
    /* QEMU uses translated PC scancodes internally.  To avoid multiple
92 f94f5d71 pbrook
       conversions we do the translation (if any) in the PS/2 emulation
93 f94f5d71 pbrook
       not the keyboard controller.  */
94 f94f5d71 pbrook
    int translate;
95 e7d93956 aurel32
    int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
96 7f540ab5 Christophe Fergeau
    int ledstate;
97 0e43e99c bellard
} PS2KbdState;
98 0e43e99c bellard
99 0e43e99c bellard
typedef struct {
100 0e43e99c bellard
    PS2State common;
101 0e43e99c bellard
    uint8_t mouse_status;
102 0e43e99c bellard
    uint8_t mouse_resolution;
103 0e43e99c bellard
    uint8_t mouse_sample_rate;
104 0e43e99c bellard
    uint8_t mouse_wrap;
105 0e43e99c bellard
    uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
106 0e43e99c bellard
    uint8_t mouse_detect_state;
107 0e43e99c bellard
    int mouse_dx; /* current values, needed for 'poll' mode */
108 0e43e99c bellard
    int mouse_dy;
109 0e43e99c bellard
    int mouse_dz;
110 0e43e99c bellard
    uint8_t mouse_buttons;
111 0e43e99c bellard
} PS2MouseState;
112 0e43e99c bellard
113 f94f5d71 pbrook
/* Table to convert from PC scancodes to raw scancodes.  */
114 f94f5d71 pbrook
static const unsigned char ps2_raw_keycode[128] = {
115 7096a96d Roy Tam
  0, 118,  22,  30,  38,  37,  46,  54,  61,  62,  70,  69,  78,  85, 102,  13,
116 7096a96d Roy Tam
 21,  29,  36,  45,  44,  53,  60,  67,  68,  77,  84,  91,  90,  20,  28,  27,
117 7096a96d Roy Tam
 35,  43,  52,  51,  59,  66,  75,  76,  82,  14,  18,  93,  26,  34,  33,  42,
118 7096a96d Roy Tam
 50,  49,  58,  65,  73,  74,  89, 124,  17,  41,  88,   5,   6,   4,  12,   3,
119 7096a96d Roy Tam
 11,   2,  10,   1,   9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105,
120 7096a96d Roy Tam
114, 122, 112, 113, 127,  96,  97, 120,   7,  15,  23,  31,  39,  47,  55,  63,
121 7096a96d Roy Tam
 71,  79,  86,  94,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  87, 111,
122 7096a96d Roy Tam
 19,  25,  57,  81,  83,  92,  95,  98,  99, 100, 101, 103, 104, 106, 109, 110
123 7096a96d Roy Tam
};
124 7096a96d Roy Tam
static const unsigned char ps2_raw_keycode_set3[128] = {
125 7096a96d Roy Tam
  0,   8,  22,  30,  38,  37,  46,  54,  61,  62,  70,  69,  78,  85, 102,  13,
126 7096a96d Roy Tam
 21,  29,  36,  45,  44,  53,  60,  67,  68,  77,  84,  91,  90,  17,  28,  27,
127 7096a96d Roy Tam
 35,  43,  52,  51,  59,  66,  75,  76,  82,  14,  18,  92,  26,  34,  33,  42,
128 7096a96d Roy Tam
 50,  49,  58,  65,  73,  74,  89, 126,  25,  41,  20,   7,  15,  23,  31,  39,
129 7096a96d Roy Tam
 47,   2,  63,  71,  79, 118,  95, 108, 117, 125, 132, 107, 115, 116, 124, 105,
130 7096a96d Roy Tam
114, 122, 112, 113, 127,  96,  97,  86,  94,  15,  23,  31,  39,  47,  55,  63,
131 7096a96d Roy Tam
 71,  79,  86,  94,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  87, 111,
132 7096a96d Roy Tam
 19,  25,  57,  81,  83,  92,  95,  98,  99, 100, 101, 103, 104, 106, 109, 110
133 f94f5d71 pbrook
};
134 f94f5d71 pbrook
135 0e43e99c bellard
void ps2_queue(void *opaque, int b)
136 0e43e99c bellard
{
137 0e43e99c bellard
    PS2State *s = (PS2State *)opaque;
138 0e43e99c bellard
    PS2Queue *q = &s->queue;
139 0e43e99c bellard
140 0e43e99c bellard
    if (q->count >= PS2_QUEUE_SIZE)
141 0e43e99c bellard
        return;
142 0e43e99c bellard
    q->data[q->wptr] = b;
143 0e43e99c bellard
    if (++q->wptr == PS2_QUEUE_SIZE)
144 0e43e99c bellard
        q->wptr = 0;
145 0e43e99c bellard
    q->count++;
146 0e43e99c bellard
    s->update_irq(s->update_arg, 1);
147 0e43e99c bellard
}
148 0e43e99c bellard
149 35c4d671 aurel32
/*
150 35c4d671 aurel32
   keycode is expressed as follow:
151 35c4d671 aurel32
   bit 7    - 0 key pressed, 1 = key released
152 35c4d671 aurel32
   bits 6-0 - translated scancode set 2
153 35c4d671 aurel32
 */
154 0e43e99c bellard
static void ps2_put_keycode(void *opaque, int keycode)
155 0e43e99c bellard
{
156 f94f5d71 pbrook
    PS2KbdState *s = opaque;
157 e7d93956 aurel32
158 fd214d18 Gerd Hoffmann
    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
159 7096a96d Roy Tam
    /* XXX: add support for scancode set 1 */
160 7096a96d Roy Tam
    if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) {
161 7096a96d Roy Tam
        if (keycode & 0x80) {
162 f94f5d71 pbrook
            ps2_queue(&s->common, 0xf0);
163 7096a96d Roy Tam
        }
164 7096a96d Roy Tam
        if (s->scancode_set == 2) {
165 7096a96d Roy Tam
            keycode = ps2_raw_keycode[keycode & 0x7f];
166 7096a96d Roy Tam
        } else if (s->scancode_set == 3) {
167 7096a96d Roy Tam
            keycode = ps2_raw_keycode_set3[keycode & 0x7f];
168 7096a96d Roy Tam
        }
169 f94f5d71 pbrook
      }
170 0e43e99c bellard
    ps2_queue(&s->common, keycode);
171 0e43e99c bellard
}
172 0e43e99c bellard
173 0e43e99c bellard
uint32_t ps2_read_data(void *opaque)
174 0e43e99c bellard
{
175 0e43e99c bellard
    PS2State *s = (PS2State *)opaque;
176 0e43e99c bellard
    PS2Queue *q;
177 0e43e99c bellard
    int val, index;
178 3b46e624 ths
179 0e43e99c bellard
    q = &s->queue;
180 0e43e99c bellard
    if (q->count == 0) {
181 0e43e99c bellard
        /* NOTE: if no data left, we return the last keyboard one
182 0e43e99c bellard
           (needed for EMM386) */
183 0e43e99c bellard
        /* XXX: need a timer to do things correctly */
184 0e43e99c bellard
        index = q->rptr - 1;
185 0e43e99c bellard
        if (index < 0)
186 0e43e99c bellard
            index = PS2_QUEUE_SIZE - 1;
187 0e43e99c bellard
        val = q->data[index];
188 0e43e99c bellard
    } else {
189 0e43e99c bellard
        val = q->data[q->rptr];
190 0e43e99c bellard
        if (++q->rptr == PS2_QUEUE_SIZE)
191 0e43e99c bellard
            q->rptr = 0;
192 0e43e99c bellard
        q->count--;
193 0e43e99c bellard
        /* reading deasserts IRQ */
194 0e43e99c bellard
        s->update_irq(s->update_arg, 0);
195 0e43e99c bellard
        /* reassert IRQs if data left */
196 0e43e99c bellard
        s->update_irq(s->update_arg, q->count != 0);
197 0e43e99c bellard
    }
198 0e43e99c bellard
    return val;
199 0e43e99c bellard
}
200 0e43e99c bellard
201 7f540ab5 Christophe Fergeau
static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
202 7f540ab5 Christophe Fergeau
{
203 7f540ab5 Christophe Fergeau
    s->ledstate = ledstate;
204 7f540ab5 Christophe Fergeau
    kbd_put_ledstate(ledstate);
205 7f540ab5 Christophe Fergeau
}
206 7f540ab5 Christophe Fergeau
207 0e43e99c bellard
static void ps2_reset_keyboard(PS2KbdState *s)
208 0e43e99c bellard
{
209 0e43e99c bellard
    s->scan_enabled = 1;
210 e7d93956 aurel32
    s->scancode_set = 2;
211 7f540ab5 Christophe Fergeau
    ps2_set_ledstate(s, 0);
212 0e43e99c bellard
}
213 0e43e99c bellard
214 0e43e99c bellard
void ps2_write_keyboard(void *opaque, int val)
215 0e43e99c bellard
{
216 0e43e99c bellard
    PS2KbdState *s = (PS2KbdState *)opaque;
217 0e43e99c bellard
218 0e43e99c bellard
    switch(s->common.write_cmd) {
219 0e43e99c bellard
    default:
220 0e43e99c bellard
    case -1:
221 0e43e99c bellard
        switch(val) {
222 0e43e99c bellard
        case 0x00:
223 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
224 0e43e99c bellard
            break;
225 0e43e99c bellard
        case 0x05:
226 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_RESEND);
227 0e43e99c bellard
            break;
228 0e43e99c bellard
        case KBD_CMD_GET_ID:
229 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
230 e7d93956 aurel32
            /* We emulate a MF2 AT keyboard here */
231 35c4d671 aurel32
            ps2_queue(&s->common, KBD_REPLY_ID);
232 35c4d671 aurel32
            if (s->translate)
233 35c4d671 aurel32
                ps2_queue(&s->common, 0x41);
234 35c4d671 aurel32
            else
235 35c4d671 aurel32
                ps2_queue(&s->common, 0x83);
236 0e43e99c bellard
            break;
237 0e43e99c bellard
        case KBD_CMD_ECHO:
238 0e43e99c bellard
            ps2_queue(&s->common, KBD_CMD_ECHO);
239 0e43e99c bellard
            break;
240 0e43e99c bellard
        case KBD_CMD_ENABLE:
241 0e43e99c bellard
            s->scan_enabled = 1;
242 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
243 0e43e99c bellard
            break;
244 e7d93956 aurel32
        case KBD_CMD_SCANCODE:
245 0e43e99c bellard
        case KBD_CMD_SET_LEDS:
246 0e43e99c bellard
        case KBD_CMD_SET_RATE:
247 0e43e99c bellard
            s->common.write_cmd = val;
248 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
249 0e43e99c bellard
            break;
250 0e43e99c bellard
        case KBD_CMD_RESET_DISABLE:
251 0e43e99c bellard
            ps2_reset_keyboard(s);
252 0e43e99c bellard
            s->scan_enabled = 0;
253 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
254 0e43e99c bellard
            break;
255 0e43e99c bellard
        case KBD_CMD_RESET_ENABLE:
256 0e43e99c bellard
            ps2_reset_keyboard(s);
257 0e43e99c bellard
            s->scan_enabled = 1;
258 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
259 0e43e99c bellard
            break;
260 0e43e99c bellard
        case KBD_CMD_RESET:
261 0e43e99c bellard
            ps2_reset_keyboard(s);
262 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
263 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_POR);
264 0e43e99c bellard
            break;
265 0e43e99c bellard
        default:
266 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
267 0e43e99c bellard
            break;
268 0e43e99c bellard
        }
269 0e43e99c bellard
        break;
270 e7d93956 aurel32
    case KBD_CMD_SCANCODE:
271 e7d93956 aurel32
        if (val == 0) {
272 e7d93956 aurel32
            if (s->scancode_set == 1)
273 e7d93956 aurel32
                ps2_put_keycode(s, 0x43);
274 e7d93956 aurel32
            else if (s->scancode_set == 2)
275 e7d93956 aurel32
                ps2_put_keycode(s, 0x41);
276 e7d93956 aurel32
            else if (s->scancode_set == 3)
277 e7d93956 aurel32
                ps2_put_keycode(s, 0x3f);
278 e7d93956 aurel32
        } else {
279 e7d93956 aurel32
            if (val >= 1 && val <= 3)
280 e7d93956 aurel32
                s->scancode_set = val;
281 e7d93956 aurel32
            ps2_queue(&s->common, KBD_REPLY_ACK);
282 e7d93956 aurel32
        }
283 e7d93956 aurel32
        s->common.write_cmd = -1;
284 e7d93956 aurel32
        break;
285 0e43e99c bellard
    case KBD_CMD_SET_LEDS:
286 7f540ab5 Christophe Fergeau
        ps2_set_ledstate(s, val);
287 0e43e99c bellard
        ps2_queue(&s->common, KBD_REPLY_ACK);
288 0e43e99c bellard
        s->common.write_cmd = -1;
289 0e43e99c bellard
        break;
290 0e43e99c bellard
    case KBD_CMD_SET_RATE:
291 0e43e99c bellard
        ps2_queue(&s->common, KBD_REPLY_ACK);
292 0e43e99c bellard
        s->common.write_cmd = -1;
293 0e43e99c bellard
        break;
294 0e43e99c bellard
    }
295 0e43e99c bellard
}
296 0e43e99c bellard
297 f94f5d71 pbrook
/* Set the scancode translation mode.
298 f94f5d71 pbrook
   0 = raw scancodes.
299 f94f5d71 pbrook
   1 = translated scancodes (used by qemu internally).  */
300 f94f5d71 pbrook
301 f94f5d71 pbrook
void ps2_keyboard_set_translation(void *opaque, int mode)
302 f94f5d71 pbrook
{
303 f94f5d71 pbrook
    PS2KbdState *s = (PS2KbdState *)opaque;
304 f94f5d71 pbrook
    s->translate = mode;
305 f94f5d71 pbrook
}
306 f94f5d71 pbrook
307 0e43e99c bellard
static void ps2_mouse_send_packet(PS2MouseState *s)
308 0e43e99c bellard
{
309 0e43e99c bellard
    unsigned int b;
310 0e43e99c bellard
    int dx1, dy1, dz1;
311 0e43e99c bellard
312 0e43e99c bellard
    dx1 = s->mouse_dx;
313 0e43e99c bellard
    dy1 = s->mouse_dy;
314 0e43e99c bellard
    dz1 = s->mouse_dz;
315 0e43e99c bellard
    /* XXX: increase range to 8 bits ? */
316 0e43e99c bellard
    if (dx1 > 127)
317 0e43e99c bellard
        dx1 = 127;
318 0e43e99c bellard
    else if (dx1 < -127)
319 0e43e99c bellard
        dx1 = -127;
320 0e43e99c bellard
    if (dy1 > 127)
321 0e43e99c bellard
        dy1 = 127;
322 0e43e99c bellard
    else if (dy1 < -127)
323 0e43e99c bellard
        dy1 = -127;
324 0e43e99c bellard
    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
325 0e43e99c bellard
    ps2_queue(&s->common, b);
326 0e43e99c bellard
    ps2_queue(&s->common, dx1 & 0xff);
327 0e43e99c bellard
    ps2_queue(&s->common, dy1 & 0xff);
328 0e43e99c bellard
    /* extra byte for IMPS/2 or IMEX */
329 0e43e99c bellard
    switch(s->mouse_type) {
330 0e43e99c bellard
    default:
331 0e43e99c bellard
        break;
332 0e43e99c bellard
    case 3:
333 0e43e99c bellard
        if (dz1 > 127)
334 0e43e99c bellard
            dz1 = 127;
335 0e43e99c bellard
        else if (dz1 < -127)
336 0e43e99c bellard
                dz1 = -127;
337 0e43e99c bellard
        ps2_queue(&s->common, dz1 & 0xff);
338 0e43e99c bellard
        break;
339 0e43e99c bellard
    case 4:
340 0e43e99c bellard
        if (dz1 > 7)
341 0e43e99c bellard
            dz1 = 7;
342 0e43e99c bellard
        else if (dz1 < -7)
343 0e43e99c bellard
            dz1 = -7;
344 0e43e99c bellard
        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
345 0e43e99c bellard
        ps2_queue(&s->common, b);
346 0e43e99c bellard
        break;
347 0e43e99c bellard
    }
348 0e43e99c bellard
349 0e43e99c bellard
    /* update deltas */
350 0e43e99c bellard
    s->mouse_dx -= dx1;
351 0e43e99c bellard
    s->mouse_dy -= dy1;
352 0e43e99c bellard
    s->mouse_dz -= dz1;
353 0e43e99c bellard
}
354 0e43e99c bellard
355 5fafdf24 ths
static void ps2_mouse_event(void *opaque,
356 0e43e99c bellard
                            int dx, int dy, int dz, int buttons_state)
357 0e43e99c bellard
{
358 0e43e99c bellard
    PS2MouseState *s = opaque;
359 0e43e99c bellard
360 0e43e99c bellard
    /* check if deltas are recorded when disabled */
361 0e43e99c bellard
    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
362 0e43e99c bellard
        return;
363 0e43e99c bellard
364 0e43e99c bellard
    s->mouse_dx += dx;
365 0e43e99c bellard
    s->mouse_dy -= dy;
366 0e43e99c bellard
    s->mouse_dz += dz;
367 0e43e99c bellard
    /* XXX: SDL sometimes generates nul events: we delete them */
368 0e43e99c bellard
    if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
369 0e43e99c bellard
        s->mouse_buttons == buttons_state)
370 0e43e99c bellard
        return;
371 0e43e99c bellard
    s->mouse_buttons = buttons_state;
372 3b46e624 ths
373 fd214d18 Gerd Hoffmann
    if (buttons_state) {
374 fd214d18 Gerd Hoffmann
        qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
375 fd214d18 Gerd Hoffmann
    }
376 fd214d18 Gerd Hoffmann
377 0e43e99c bellard
    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
378 0e43e99c bellard
        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
379 0e43e99c bellard
        for(;;) {
380 0e43e99c bellard
            /* if not remote, send event. Multiple events are sent if
381 0e43e99c bellard
               too big deltas */
382 0e43e99c bellard
            ps2_mouse_send_packet(s);
383 0e43e99c bellard
            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
384 0e43e99c bellard
                break;
385 0e43e99c bellard
        }
386 0e43e99c bellard
    }
387 0e43e99c bellard
}
388 0e43e99c bellard
389 548df2ac ths
void ps2_mouse_fake_event(void *opaque)
390 548df2ac ths
{
391 548df2ac ths
    ps2_mouse_event(opaque, 1, 0, 0, 0);
392 548df2ac ths
}
393 548df2ac ths
394 0e43e99c bellard
void ps2_write_mouse(void *opaque, int val)
395 0e43e99c bellard
{
396 0e43e99c bellard
    PS2MouseState *s = (PS2MouseState *)opaque;
397 0e43e99c bellard
#ifdef DEBUG_MOUSE
398 0e43e99c bellard
    printf("kbd: write mouse 0x%02x\n", val);
399 0e43e99c bellard
#endif
400 0e43e99c bellard
    switch(s->common.write_cmd) {
401 0e43e99c bellard
    default:
402 0e43e99c bellard
    case -1:
403 0e43e99c bellard
        /* mouse command */
404 0e43e99c bellard
        if (s->mouse_wrap) {
405 0e43e99c bellard
            if (val == AUX_RESET_WRAP) {
406 0e43e99c bellard
                s->mouse_wrap = 0;
407 0e43e99c bellard
                ps2_queue(&s->common, AUX_ACK);
408 0e43e99c bellard
                return;
409 0e43e99c bellard
            } else if (val != AUX_RESET) {
410 0e43e99c bellard
                ps2_queue(&s->common, val);
411 0e43e99c bellard
                return;
412 0e43e99c bellard
            }
413 0e43e99c bellard
        }
414 0e43e99c bellard
        switch(val) {
415 0e43e99c bellard
        case AUX_SET_SCALE11:
416 0e43e99c bellard
            s->mouse_status &= ~MOUSE_STATUS_SCALE21;
417 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
418 0e43e99c bellard
            break;
419 0e43e99c bellard
        case AUX_SET_SCALE21:
420 0e43e99c bellard
            s->mouse_status |= MOUSE_STATUS_SCALE21;
421 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
422 0e43e99c bellard
            break;
423 0e43e99c bellard
        case AUX_SET_STREAM:
424 0e43e99c bellard
            s->mouse_status &= ~MOUSE_STATUS_REMOTE;
425 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
426 0e43e99c bellard
            break;
427 0e43e99c bellard
        case AUX_SET_WRAP:
428 0e43e99c bellard
            s->mouse_wrap = 1;
429 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
430 0e43e99c bellard
            break;
431 0e43e99c bellard
        case AUX_SET_REMOTE:
432 0e43e99c bellard
            s->mouse_status |= MOUSE_STATUS_REMOTE;
433 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
434 0e43e99c bellard
            break;
435 0e43e99c bellard
        case AUX_GET_TYPE:
436 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
437 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_type);
438 0e43e99c bellard
            break;
439 0e43e99c bellard
        case AUX_SET_RES:
440 0e43e99c bellard
        case AUX_SET_SAMPLE:
441 0e43e99c bellard
            s->common.write_cmd = val;
442 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
443 0e43e99c bellard
            break;
444 0e43e99c bellard
        case AUX_GET_SCALE:
445 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
446 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_status);
447 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_resolution);
448 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_sample_rate);
449 0e43e99c bellard
            break;
450 0e43e99c bellard
        case AUX_POLL:
451 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
452 0e43e99c bellard
            ps2_mouse_send_packet(s);
453 0e43e99c bellard
            break;
454 0e43e99c bellard
        case AUX_ENABLE_DEV:
455 0e43e99c bellard
            s->mouse_status |= MOUSE_STATUS_ENABLED;
456 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
457 0e43e99c bellard
            break;
458 0e43e99c bellard
        case AUX_DISABLE_DEV:
459 0e43e99c bellard
            s->mouse_status &= ~MOUSE_STATUS_ENABLED;
460 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
461 0e43e99c bellard
            break;
462 0e43e99c bellard
        case AUX_SET_DEFAULT:
463 0e43e99c bellard
            s->mouse_sample_rate = 100;
464 0e43e99c bellard
            s->mouse_resolution = 2;
465 0e43e99c bellard
            s->mouse_status = 0;
466 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
467 0e43e99c bellard
            break;
468 0e43e99c bellard
        case AUX_RESET:
469 0e43e99c bellard
            s->mouse_sample_rate = 100;
470 0e43e99c bellard
            s->mouse_resolution = 2;
471 0e43e99c bellard
            s->mouse_status = 0;
472 0e43e99c bellard
            s->mouse_type = 0;
473 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
474 0e43e99c bellard
            ps2_queue(&s->common, 0xaa);
475 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_type);
476 0e43e99c bellard
            break;
477 0e43e99c bellard
        default:
478 0e43e99c bellard
            break;
479 0e43e99c bellard
        }
480 0e43e99c bellard
        break;
481 0e43e99c bellard
    case AUX_SET_SAMPLE:
482 0e43e99c bellard
        s->mouse_sample_rate = val;
483 0e43e99c bellard
        /* detect IMPS/2 or IMEX */
484 0e43e99c bellard
        switch(s->mouse_detect_state) {
485 0e43e99c bellard
        default:
486 0e43e99c bellard
        case 0:
487 0e43e99c bellard
            if (val == 200)
488 0e43e99c bellard
                s->mouse_detect_state = 1;
489 0e43e99c bellard
            break;
490 0e43e99c bellard
        case 1:
491 0e43e99c bellard
            if (val == 100)
492 0e43e99c bellard
                s->mouse_detect_state = 2;
493 0e43e99c bellard
            else if (val == 200)
494 0e43e99c bellard
                s->mouse_detect_state = 3;
495 0e43e99c bellard
            else
496 0e43e99c bellard
                s->mouse_detect_state = 0;
497 0e43e99c bellard
            break;
498 0e43e99c bellard
        case 2:
499 5fafdf24 ths
            if (val == 80)
500 0e43e99c bellard
                s->mouse_type = 3; /* IMPS/2 */
501 0e43e99c bellard
            s->mouse_detect_state = 0;
502 0e43e99c bellard
            break;
503 0e43e99c bellard
        case 3:
504 5fafdf24 ths
            if (val == 80)
505 0e43e99c bellard
                s->mouse_type = 4; /* IMEX */
506 0e43e99c bellard
            s->mouse_detect_state = 0;
507 0e43e99c bellard
            break;
508 0e43e99c bellard
        }
509 0e43e99c bellard
        ps2_queue(&s->common, AUX_ACK);
510 0e43e99c bellard
        s->common.write_cmd = -1;
511 0e43e99c bellard
        break;
512 0e43e99c bellard
    case AUX_SET_RES:
513 0e43e99c bellard
        s->mouse_resolution = val;
514 0e43e99c bellard
        ps2_queue(&s->common, AUX_ACK);
515 0e43e99c bellard
        s->common.write_cmd = -1;
516 0e43e99c bellard
        break;
517 0e43e99c bellard
    }
518 0e43e99c bellard
}
519 0e43e99c bellard
520 ef74679a Dinesh Subhraveti
static void ps2_common_reset(PS2State *s)
521 0e43e99c bellard
{
522 0e43e99c bellard
    PS2Queue *q;
523 0e43e99c bellard
    s->write_cmd = -1;
524 0e43e99c bellard
    q = &s->queue;
525 0e43e99c bellard
    q->rptr = 0;
526 0e43e99c bellard
    q->wptr = 0;
527 0e43e99c bellard
    q->count = 0;
528 deeccef3 aliguori
    s->update_irq(s->update_arg, 0);
529 0e43e99c bellard
}
530 0e43e99c bellard
531 ef74679a Dinesh Subhraveti
static void ps2_kbd_reset(void *opaque)
532 ef74679a Dinesh Subhraveti
{
533 ef74679a Dinesh Subhraveti
    PS2KbdState *s = (PS2KbdState *) opaque;
534 ef74679a Dinesh Subhraveti
535 ef74679a Dinesh Subhraveti
    ps2_common_reset(&s->common);
536 ef74679a Dinesh Subhraveti
    s->scan_enabled = 0;
537 ef74679a Dinesh Subhraveti
    s->translate = 0;
538 ef74679a Dinesh Subhraveti
    s->scancode_set = 0;
539 ef74679a Dinesh Subhraveti
}
540 ef74679a Dinesh Subhraveti
541 ef74679a Dinesh Subhraveti
static void ps2_mouse_reset(void *opaque)
542 ef74679a Dinesh Subhraveti
{
543 ef74679a Dinesh Subhraveti
    PS2MouseState *s = (PS2MouseState *) opaque;
544 ef74679a Dinesh Subhraveti
545 ef74679a Dinesh Subhraveti
    ps2_common_reset(&s->common);
546 ef74679a Dinesh Subhraveti
    s->mouse_status = 0;
547 ef74679a Dinesh Subhraveti
    s->mouse_resolution = 0;
548 ef74679a Dinesh Subhraveti
    s->mouse_sample_rate = 0;
549 ef74679a Dinesh Subhraveti
    s->mouse_wrap = 0;
550 ef74679a Dinesh Subhraveti
    s->mouse_type = 0;
551 ef74679a Dinesh Subhraveti
    s->mouse_detect_state = 0;
552 ef74679a Dinesh Subhraveti
    s->mouse_dx = 0;
553 ef74679a Dinesh Subhraveti
    s->mouse_dy = 0;
554 ef74679a Dinesh Subhraveti
    s->mouse_dz = 0;
555 ef74679a Dinesh Subhraveti
    s->mouse_buttons = 0;
556 ef74679a Dinesh Subhraveti
}
557 ef74679a Dinesh Subhraveti
558 b31442c3 Juan Quintela
static const VMStateDescription vmstate_ps2_common = {
559 b31442c3 Juan Quintela
    .name = "PS2 Common State",
560 b31442c3 Juan Quintela
    .version_id = 3,
561 b31442c3 Juan Quintela
    .minimum_version_id = 2,
562 b31442c3 Juan Quintela
    .minimum_version_id_old = 2,
563 b31442c3 Juan Quintela
    .fields      = (VMStateField []) {
564 b31442c3 Juan Quintela
        VMSTATE_INT32(write_cmd, PS2State),
565 b31442c3 Juan Quintela
        VMSTATE_INT32(queue.rptr, PS2State),
566 b31442c3 Juan Quintela
        VMSTATE_INT32(queue.wptr, PS2State),
567 b31442c3 Juan Quintela
        VMSTATE_INT32(queue.count, PS2State),
568 b31442c3 Juan Quintela
        VMSTATE_BUFFER(queue.data, PS2State),
569 b31442c3 Juan Quintela
        VMSTATE_END_OF_LIST()
570 b31442c3 Juan Quintela
    }
571 b31442c3 Juan Quintela
};
572 0e43e99c bellard
573 7f540ab5 Christophe Fergeau
static bool ps2_keyboard_ledstate_needed(void *opaque)
574 7f540ab5 Christophe Fergeau
{
575 7f540ab5 Christophe Fergeau
    PS2KbdState *s = opaque;
576 7f540ab5 Christophe Fergeau
577 7f540ab5 Christophe Fergeau
    return s->ledstate != 0; /* 0 is default state */
578 7f540ab5 Christophe Fergeau
}
579 7f540ab5 Christophe Fergeau
580 7f540ab5 Christophe Fergeau
static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
581 7f540ab5 Christophe Fergeau
{
582 7f540ab5 Christophe Fergeau
    PS2KbdState *s = opaque;
583 7f540ab5 Christophe Fergeau
584 7f540ab5 Christophe Fergeau
    kbd_put_ledstate(s->ledstate);
585 7f540ab5 Christophe Fergeau
    return 0;
586 7f540ab5 Christophe Fergeau
}
587 7f540ab5 Christophe Fergeau
588 7f540ab5 Christophe Fergeau
static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
589 7f540ab5 Christophe Fergeau
    .name = "ps2kbd/ledstate",
590 7f540ab5 Christophe Fergeau
    .version_id = 3,
591 7f540ab5 Christophe Fergeau
    .minimum_version_id = 2,
592 7f540ab5 Christophe Fergeau
    .minimum_version_id_old = 2,
593 7f540ab5 Christophe Fergeau
    .post_load = ps2_kbd_ledstate_post_load,
594 7f540ab5 Christophe Fergeau
    .fields      = (VMStateField []) {
595 7f540ab5 Christophe Fergeau
        VMSTATE_INT32(ledstate, PS2KbdState),
596 7f540ab5 Christophe Fergeau
        VMSTATE_END_OF_LIST()
597 7f540ab5 Christophe Fergeau
    }
598 7f540ab5 Christophe Fergeau
};
599 7f540ab5 Christophe Fergeau
600 db596c53 Juan Quintela
static int ps2_kbd_post_load(void* opaque, int version_id)
601 0e43e99c bellard
{
602 0e43e99c bellard
    PS2KbdState *s = (PS2KbdState*)opaque;
603 7783e9f0 pbrook
604 db596c53 Juan Quintela
    if (version_id == 2)
605 e7d93956 aurel32
        s->scancode_set=2;
606 0e43e99c bellard
    return 0;
607 0e43e99c bellard
}
608 0e43e99c bellard
609 b31442c3 Juan Quintela
static const VMStateDescription vmstate_ps2_keyboard = {
610 b31442c3 Juan Quintela
    .name = "ps2kbd",
611 b31442c3 Juan Quintela
    .version_id = 3,
612 db596c53 Juan Quintela
    .minimum_version_id = 2,
613 b31442c3 Juan Quintela
    .minimum_version_id_old = 2,
614 db596c53 Juan Quintela
    .post_load = ps2_kbd_post_load,
615 b31442c3 Juan Quintela
    .fields      = (VMStateField []) {
616 b31442c3 Juan Quintela
        VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
617 b31442c3 Juan Quintela
        VMSTATE_INT32(scan_enabled, PS2KbdState),
618 b31442c3 Juan Quintela
        VMSTATE_INT32(translate, PS2KbdState),
619 b31442c3 Juan Quintela
        VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
620 b31442c3 Juan Quintela
        VMSTATE_END_OF_LIST()
621 7f540ab5 Christophe Fergeau
    },
622 7f540ab5 Christophe Fergeau
    .subsections = (VMStateSubsection []) {
623 7f540ab5 Christophe Fergeau
        {
624 7f540ab5 Christophe Fergeau
            .vmsd = &vmstate_ps2_keyboard_ledstate,
625 7f540ab5 Christophe Fergeau
            .needed = ps2_keyboard_ledstate_needed,
626 7f540ab5 Christophe Fergeau
        }, {
627 7f540ab5 Christophe Fergeau
            /* empty */
628 7f540ab5 Christophe Fergeau
        }
629 b31442c3 Juan Quintela
    }
630 b31442c3 Juan Quintela
};
631 7783e9f0 pbrook
632 b31442c3 Juan Quintela
static const VMStateDescription vmstate_ps2_mouse = {
633 b31442c3 Juan Quintela
    .name = "ps2mouse",
634 b31442c3 Juan Quintela
    .version_id = 2,
635 b31442c3 Juan Quintela
    .minimum_version_id = 2,
636 b31442c3 Juan Quintela
    .minimum_version_id_old = 2,
637 b31442c3 Juan Quintela
    .fields      = (VMStateField []) {
638 b31442c3 Juan Quintela
        VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
639 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_status, PS2MouseState),
640 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_resolution, PS2MouseState),
641 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
642 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_wrap, PS2MouseState),
643 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_type, PS2MouseState),
644 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
645 b31442c3 Juan Quintela
        VMSTATE_INT32(mouse_dx, PS2MouseState),
646 b31442c3 Juan Quintela
        VMSTATE_INT32(mouse_dy, PS2MouseState),
647 b31442c3 Juan Quintela
        VMSTATE_INT32(mouse_dz, PS2MouseState),
648 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_buttons, PS2MouseState),
649 b31442c3 Juan Quintela
        VMSTATE_END_OF_LIST()
650 b31442c3 Juan Quintela
    }
651 b31442c3 Juan Quintela
};
652 0e43e99c bellard
653 0e43e99c bellard
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
654 0e43e99c bellard
{
655 7267c094 Anthony Liguori
    PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
656 0e43e99c bellard
657 0e43e99c bellard
    s->common.update_irq = update_irq;
658 0e43e99c bellard
    s->common.update_arg = update_arg;
659 e7d93956 aurel32
    s->scancode_set = 2;
660 0be71e32 Alex Williamson
    vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
661 0e43e99c bellard
    qemu_add_kbd_event_handler(ps2_put_keycode, s);
662 ef74679a Dinesh Subhraveti
    qemu_register_reset(ps2_kbd_reset, s);
663 0e43e99c bellard
    return s;
664 0e43e99c bellard
}
665 0e43e99c bellard
666 0e43e99c bellard
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
667 0e43e99c bellard
{
668 7267c094 Anthony Liguori
    PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
669 0e43e99c bellard
670 0e43e99c bellard
    s->common.update_irq = update_irq;
671 0e43e99c bellard
    s->common.update_arg = update_arg;
672 0be71e32 Alex Williamson
    vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
673 455204eb ths
    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
674 ef74679a Dinesh Subhraveti
    qemu_register_reset(ps2_mouse_reset, s);
675 0e43e99c bellard
    return s;
676 0e43e99c bellard
}