186797937017f52bff088d02edf64fb931177a7eaJun Nakajima/*
286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * QEMU PS/2 keyboard/mouse emulation
386797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
486797937017f52bff088d02edf64fb931177a7eaJun Nakajima * Copyright (c) 2003 Fabrice Bellard
586797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
686797937017f52bff088d02edf64fb931177a7eaJun Nakajima * Permission is hereby granted, free of charge, to any person obtaining a copy
786797937017f52bff088d02edf64fb931177a7eaJun Nakajima * of this software and associated documentation files (the "Software"), to deal
886797937017f52bff088d02edf64fb931177a7eaJun Nakajima * in the Software without restriction, including without limitation the rights
986797937017f52bff088d02edf64fb931177a7eaJun Nakajima * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1086797937017f52bff088d02edf64fb931177a7eaJun Nakajima * copies of the Software, and to permit persons to whom the Software is
1186797937017f52bff088d02edf64fb931177a7eaJun Nakajima * furnished to do so, subject to the following conditions:
1286797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
1386797937017f52bff088d02edf64fb931177a7eaJun Nakajima * The above copyright notice and this permission notice shall be included in
1486797937017f52bff088d02edf64fb931177a7eaJun Nakajima * all copies or substantial portions of the Software.
1586797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
1686797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1786797937017f52bff088d02edf64fb931177a7eaJun Nakajima * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1886797937017f52bff088d02edf64fb931177a7eaJun Nakajima * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1986797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2086797937017f52bff088d02edf64fb931177a7eaJun Nakajima * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2186797937017f52bff088d02edf64fb931177a7eaJun Nakajima * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE SOFTWARE.
2386797937017f52bff088d02edf64fb931177a7eaJun Nakajima */
2486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "hw.h"
2586797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "ps2.h"
2686797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "console.h"
2786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
2886797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* debug PC keyboard */
2986797937017f52bff088d02edf64fb931177a7eaJun Nakajima//#define DEBUG_KBD
3086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
3186797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* debug PC keyboard : only mouse */
3286797937017f52bff088d02edf64fb931177a7eaJun Nakajima//#define DEBUG_MOUSE
3386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
3486797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* Keyboard Commands */
3586797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_CMD_SET_LEDS	0xED	/* Set keyboard leds */
3686797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_CMD_ECHO     	0xEE
3786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_CMD_SCANCODE	0xF0	/* Get/set scancode set */
3886797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_CMD_GET_ID 	        0xF2	/* get keyboard ID */
3986797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_CMD_SET_RATE	0xF3	/* Set typematic rate */
4086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_CMD_ENABLE		0xF4	/* Enable scanning */
4186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_CMD_RESET_DISABLE	0xF5	/* reset and disable scanning */
4286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_CMD_RESET_ENABLE   	0xF6    /* reset and enable scanning */
4386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_CMD_RESET		0xFF	/* Reset */
4486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
4586797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* Keyboard Replies */
4686797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_REPLY_POR		0xAA	/* Power on reset */
4786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_REPLY_ID		0xAB	/* Keyboard ID */
4886797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_REPLY_ACK		0xFA	/* Command ACK */
4986797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define KBD_REPLY_RESEND	0xFE	/* Command NACK, send the cmd again */
5086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
5186797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* Mouse Commands */
5286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_SET_SCALE11		0xE6	/* Set 1:1 scaling */
5386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_SET_SCALE21		0xE7	/* Set 2:1 scaling */
5486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_SET_RES		0xE8	/* Set resolution */
5586797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_GET_SCALE		0xE9	/* Get scaling factor */
5686797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_SET_STREAM		0xEA	/* Set stream mode */
5786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_POLL		0xEB	/* Poll */
5886797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_RESET_WRAP		0xEC	/* Reset wrap mode */
5986797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_SET_WRAP		0xEE	/* Set wrap mode */
6086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_SET_REMOTE		0xF0	/* Set remote mode */
6186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_GET_TYPE		0xF2	/* Get type */
6286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_SET_SAMPLE		0xF3	/* Set sample rate */
6386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_ENABLE_DEV		0xF4	/* Enable aux device */
6486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_DISABLE_DEV		0xF5	/* Disable aux device */
6586797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_SET_DEFAULT		0xF6
6686797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_RESET		0xFF	/* Reset aux device */
6786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define AUX_ACK			0xFA	/* Command byte ACK. */
6886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
6986797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define MOUSE_STATUS_REMOTE     0x40
7086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define MOUSE_STATUS_ENABLED    0x20
7186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define MOUSE_STATUS_SCALE21    0x10
7286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
7386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define PS2_QUEUE_SIZE 256
7486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
7586797937017f52bff088d02edf64fb931177a7eaJun Nakajimatypedef struct {
7686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t data[PS2_QUEUE_SIZE];
7786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int rptr, wptr, count;
7886797937017f52bff088d02edf64fb931177a7eaJun Nakajima} PS2Queue;
7986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
8086797937017f52bff088d02edf64fb931177a7eaJun Nakajimatypedef struct {
8186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2Queue queue;
8286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int32_t write_cmd;
8386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    void (*update_irq)(void *, int);
8486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    void *update_arg;
8586797937017f52bff088d02edf64fb931177a7eaJun Nakajima} PS2State;
8686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
8786797937017f52bff088d02edf64fb931177a7eaJun Nakajimatypedef struct {
8886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2State common;
8986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int scan_enabled;
9086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* Qemu uses translated PC scancodes internally.  To avoid multiple
9186797937017f52bff088d02edf64fb931177a7eaJun Nakajima       conversions we do the translation (if any) in the PS/2 emulation
9286797937017f52bff088d02edf64fb931177a7eaJun Nakajima       not the keyboard controller.  */
9386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int translate;
9486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
9586797937017f52bff088d02edf64fb931177a7eaJun Nakajima} PS2KbdState;
9686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
9786797937017f52bff088d02edf64fb931177a7eaJun Nakajimatypedef struct {
9886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2State common;
9986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t mouse_status;
10086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t mouse_resolution;
10186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t mouse_sample_rate;
10286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t mouse_wrap;
10386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
10486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t mouse_detect_state;
10586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int mouse_dx; /* current values, needed for 'poll' mode */
10686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int mouse_dy;
10786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int mouse_dz;
10886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t mouse_buttons;
10986797937017f52bff088d02edf64fb931177a7eaJun Nakajima} PS2MouseState;
11086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
11186797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* Table to convert from PC scancodes to raw scancodes.  */
11286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic const unsigned char ps2_raw_keycode[128] = {
11386797937017f52bff088d02edf64fb931177a7eaJun Nakajima          0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
11486797937017f52bff088d02edf64fb931177a7eaJun Nakajima         21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
11586797937017f52bff088d02edf64fb931177a7eaJun Nakajima         35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
11686797937017f52bff088d02edf64fb931177a7eaJun Nakajima         50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
11786797937017f52bff088d02edf64fb931177a7eaJun Nakajima         11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
11886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
11986797937017f52bff088d02edf64fb931177a7eaJun Nakajima         71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
12086797937017f52bff088d02edf64fb931177a7eaJun Nakajima         19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
12186797937017f52bff088d02edf64fb931177a7eaJun Nakajima};
12286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
12386797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid ps2_queue(void *opaque, int b)
12486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
12586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2State *s = (PS2State *)opaque;
12686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2Queue *q = &s->queue;
12786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
12886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (q->count >= PS2_QUEUE_SIZE)
12986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
13086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    q->data[q->wptr] = b;
13186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (++q->wptr == PS2_QUEUE_SIZE)
13286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        q->wptr = 0;
13386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    q->count++;
13486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->update_irq(s->update_arg, 1);
13586797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
13686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
13786797937017f52bff088d02edf64fb931177a7eaJun Nakajima/*
13886797937017f52bff088d02edf64fb931177a7eaJun Nakajima   keycode is expressed as follow:
13986797937017f52bff088d02edf64fb931177a7eaJun Nakajima   bit 7    - 0 key pressed, 1 = key released
14086797937017f52bff088d02edf64fb931177a7eaJun Nakajima   bits 6-0 - translated scancode set 2
14186797937017f52bff088d02edf64fb931177a7eaJun Nakajima */
14286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void ps2_put_keycode(void *opaque, int keycode)
14386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
14486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2KbdState *s = opaque;
14586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
14686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* XXX: add support for scancode sets 1 and 3 */
14786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!s->translate && keycode < 0xe0 && s->scancode_set == 2)
14886797937017f52bff088d02edf64fb931177a7eaJun Nakajima      {
14986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (keycode & 0x80)
15086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, 0xf0);
15186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        keycode = ps2_raw_keycode[keycode & 0x7f];
15286797937017f52bff088d02edf64fb931177a7eaJun Nakajima      }
15386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_queue(&s->common, keycode);
15486797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
15586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
15686797937017f52bff088d02edf64fb931177a7eaJun Nakajimauint32_t ps2_read_data(void *opaque)
15786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
15886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2State *s = (PS2State *)opaque;
15986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2Queue *q;
16086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int val, index;
16186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
16286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    q = &s->queue;
16386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (q->count == 0) {
16486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* NOTE: if no data left, we return the last keyboard one
16586797937017f52bff088d02edf64fb931177a7eaJun Nakajima           (needed for EMM386) */
16686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* XXX: need a timer to do things correctly */
16786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        index = q->rptr - 1;
16886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (index < 0)
16986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            index = PS2_QUEUE_SIZE - 1;
17086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = q->data[index];
17186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    } else {
17286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = q->data[q->rptr];
17386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (++q->rptr == PS2_QUEUE_SIZE)
17486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            q->rptr = 0;
17586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        q->count--;
17686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* reading deasserts IRQ */
17786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->update_irq(s->update_arg, 0);
17886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* reassert IRQs if data left */
17986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->update_irq(s->update_arg, q->count != 0);
18086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
18186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return val;
18286797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
18386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
18486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void ps2_reset_keyboard(PS2KbdState *s)
18586797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
18686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->scan_enabled = 1;
18786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->scancode_set = 2;
18886797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
18986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
19086797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid ps2_write_keyboard(void *opaque, int val)
19186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
19286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2KbdState *s = (PS2KbdState *)opaque;
19386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
19486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch(s->common.write_cmd) {
19586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    default:
19686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case -1:
19786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        switch(val) {
19886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case 0x00:
19986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_ACK);
20086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
20186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case 0x05:
20286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_RESEND);
20386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
20486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case KBD_CMD_GET_ID:
20586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_ACK);
20686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            /* We emulate a MF2 AT keyboard here */
20786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_ID);
20886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (s->translate)
20986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                ps2_queue(&s->common, 0x41);
21086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            else
21186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                ps2_queue(&s->common, 0x83);
21286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
21386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case KBD_CMD_ECHO:
21486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_CMD_ECHO);
21586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
21686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case KBD_CMD_ENABLE:
21786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->scan_enabled = 1;
21886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_ACK);
21986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
22086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case KBD_CMD_SCANCODE:
22186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case KBD_CMD_SET_LEDS:
22286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case KBD_CMD_SET_RATE:
22386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->common.write_cmd = val;
22486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_ACK);
22586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
22686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case KBD_CMD_RESET_DISABLE:
22786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_reset_keyboard(s);
22886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->scan_enabled = 0;
22986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_ACK);
23086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
23186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case KBD_CMD_RESET_ENABLE:
23286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_reset_keyboard(s);
23386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->scan_enabled = 1;
23486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_ACK);
23586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
23686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case KBD_CMD_RESET:
23786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_reset_keyboard(s);
23886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_ACK);
23986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_POR);
24086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
24186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        default:
24286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_ACK);
24386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
24486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
24586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
24686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case KBD_CMD_SCANCODE:
24786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (val == 0) {
24886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (s->scancode_set == 1)
24986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                ps2_put_keycode(s, 0x43);
25086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            else if (s->scancode_set == 2)
25186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                ps2_put_keycode(s, 0x41);
25286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            else if (s->scancode_set == 3)
25386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                ps2_put_keycode(s, 0x3f);
25486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        } else {
25586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (val >= 1 && val <= 3)
25686797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->scancode_set = val;
25786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, KBD_REPLY_ACK);
25886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
25986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->common.write_cmd = -1;
26086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
26186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case KBD_CMD_SET_LEDS:
26286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        ps2_queue(&s->common, KBD_REPLY_ACK);
26386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->common.write_cmd = -1;
26486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
26586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case KBD_CMD_SET_RATE:
26686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        ps2_queue(&s->common, KBD_REPLY_ACK);
26786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->common.write_cmd = -1;
26886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
26986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
27086797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
27186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
27286797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* Set the scancode translation mode.
27386797937017f52bff088d02edf64fb931177a7eaJun Nakajima   0 = raw scancodes.
27486797937017f52bff088d02edf64fb931177a7eaJun Nakajima   1 = translated scancodes (used by qemu internally).  */
27586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
27686797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid ps2_keyboard_set_translation(void *opaque, int mode)
27786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
27886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2KbdState *s = (PS2KbdState *)opaque;
27986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->translate = mode;
28086797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
28186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
28286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void ps2_mouse_send_packet(PS2MouseState *s)
28386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
28486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    unsigned int b;
28586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int dx1, dy1, dz1;
28686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
28786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    dx1 = s->mouse_dx;
28886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    dy1 = s->mouse_dy;
28986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    dz1 = s->mouse_dz;
29086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* XXX: increase range to 8 bits ? */
29186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (dx1 > 127)
29286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        dx1 = 127;
29386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    else if (dx1 < -127)
29486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        dx1 = -127;
29586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (dy1 > 127)
29686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        dy1 = 127;
29786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    else if (dy1 < -127)
29886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        dy1 = -127;
29986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
30086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_queue(&s->common, b);
30186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_queue(&s->common, dx1 & 0xff);
30286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_queue(&s->common, dy1 & 0xff);
30386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* extra byte for IMPS/2 or IMEX */
30486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch(s->mouse_type) {
30586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    default:
30686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
30786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 3:
30886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (dz1 > 127)
30986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            dz1 = 127;
31086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        else if (dz1 < -127)
31186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                dz1 = -127;
31286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        ps2_queue(&s->common, dz1 & 0xff);
31386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
31486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 4:
31586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (dz1 > 7)
31686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            dz1 = 7;
31786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        else if (dz1 < -7)
31886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            dz1 = -7;
31986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
32086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        ps2_queue(&s->common, b);
32186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
32286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
32386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
32486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* update deltas */
32586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mouse_dx -= dx1;
32686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mouse_dy -= dy1;
32786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mouse_dz -= dz1;
32886797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
32986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
33086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void ps2_mouse_event(void *opaque,
33186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                            int dx, int dy, int dz, int buttons_state)
33286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
33386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2MouseState *s = opaque;
33486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
33586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* check if deltas are recorded when disabled */
33686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
33786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
33886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
33986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mouse_dx += dx;
34086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mouse_dy -= dy;
34186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mouse_dz += dz;
34286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* XXX: SDL sometimes generates nul events: we delete them */
34386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
34486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->mouse_buttons == buttons_state)
34586797937017f52bff088d02edf64fb931177a7eaJun Nakajima	return;
34686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mouse_buttons = buttons_state;
34786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
34886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
34986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
35086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        for(;;) {
35186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            /* if not remote, send event. Multiple events are sent if
35286797937017f52bff088d02edf64fb931177a7eaJun Nakajima               too big deltas */
35386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_mouse_send_packet(s);
35486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
35586797937017f52bff088d02edf64fb931177a7eaJun Nakajima                break;
35686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
35786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
35886797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
35986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
36086797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid ps2_mouse_fake_event(void *opaque)
36186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
36286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_mouse_event(opaque, 1, 0, 0, 0);
36386797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
36486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
36586797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid ps2_write_mouse(void *opaque, int val)
36686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
36786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2MouseState *s = (PS2MouseState *)opaque;
36886797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_MOUSE
36986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    printf("kbd: write mouse 0x%02x\n", val);
37086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif
37186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch(s->common.write_cmd) {
37286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    default:
37386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case -1:
37486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* mouse command */
37586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (s->mouse_wrap) {
37686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (val == AUX_RESET_WRAP) {
37786797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->mouse_wrap = 0;
37886797937017f52bff088d02edf64fb931177a7eaJun Nakajima                ps2_queue(&s->common, AUX_ACK);
37986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                return;
38086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            } else if (val != AUX_RESET) {
38186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                ps2_queue(&s->common, val);
38286797937017f52bff088d02edf64fb931177a7eaJun Nakajima                return;
38386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            }
38486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
38586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        switch(val) {
38686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_SET_SCALE11:
38786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_status &= ~MOUSE_STATUS_SCALE21;
38886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
38986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
39086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_SET_SCALE21:
39186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_status |= MOUSE_STATUS_SCALE21;
39286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
39386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
39486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_SET_STREAM:
39586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_status &= ~MOUSE_STATUS_REMOTE;
39686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
39786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
39886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_SET_WRAP:
39986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_wrap = 1;
40086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
40186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
40286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_SET_REMOTE:
40386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_status |= MOUSE_STATUS_REMOTE;
40486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
40586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
40686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_GET_TYPE:
40786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
40886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, s->mouse_type);
40986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
41086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_SET_RES:
41186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_SET_SAMPLE:
41286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->common.write_cmd = val;
41386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
41486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
41586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_GET_SCALE:
41686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
41786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, s->mouse_status);
41886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, s->mouse_resolution);
41986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, s->mouse_sample_rate);
42086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
42186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_POLL:
42286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
42386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_mouse_send_packet(s);
42486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
42586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_ENABLE_DEV:
42686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_status |= MOUSE_STATUS_ENABLED;
42786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
42886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
42986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_DISABLE_DEV:
43086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_status &= ~MOUSE_STATUS_ENABLED;
43186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
43286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
43386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_SET_DEFAULT:
43486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_sample_rate = 100;
43586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_resolution = 2;
43686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_status = 0;
43786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
43886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
43986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case AUX_RESET:
44086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_sample_rate = 100;
44186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_resolution = 2;
44286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_status = 0;
44386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_type = 0;
44486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, AUX_ACK);
44586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, 0xaa);
44686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ps2_queue(&s->common, s->mouse_type);
44786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
44886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        default:
44986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
45086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
45186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
45286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case AUX_SET_SAMPLE:
45386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->mouse_sample_rate = val;
45486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* detect IMPS/2 or IMEX */
45586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        switch(s->mouse_detect_state) {
45686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        default:
45786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case 0:
45886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (val == 200)
45986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->mouse_detect_state = 1;
46086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
46186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case 1:
46286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (val == 100)
46386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->mouse_detect_state = 2;
46486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            else if (val == 200)
46586797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->mouse_detect_state = 3;
46686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            else
46786797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->mouse_detect_state = 0;
46886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
46986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case 2:
47086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (val == 80)
47186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->mouse_type = 3; /* IMPS/2 */
47286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_detect_state = 0;
47386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
47486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case 3:
47586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (val == 80)
47686797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->mouse_type = 4; /* IMEX */
47786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->mouse_detect_state = 0;
47886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
47986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
48086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        ps2_queue(&s->common, AUX_ACK);
48186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->common.write_cmd = -1;
48286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
48386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case AUX_SET_RES:
48486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->mouse_resolution = val;
48586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        ps2_queue(&s->common, AUX_ACK);
48686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->common.write_cmd = -1;
48786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
48886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
48986797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
49086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
49186797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void ps2_reset(void *opaque)
49286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
49386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2State *s = (PS2State *)opaque;
49486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2Queue *q;
49586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->write_cmd = -1;
49686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    q = &s->queue;
49786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    q->rptr = 0;
49886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    q->wptr = 0;
49986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    q->count = 0;
50086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->update_irq(s->update_arg, 0);
50186797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
50286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
50386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void ps2_common_save (QEMUFile *f, PS2State *s)
50486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
50586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32 (f, s->write_cmd);
50686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32 (f, s->queue.rptr);
50786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32 (f, s->queue.wptr);
50886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32 (f, s->queue.count);
50986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
51086797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
51186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
51286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void ps2_common_load (QEMUFile *f, PS2State *s)
51386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
51486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->write_cmd=qemu_get_be32 (f);
51586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->queue.rptr=qemu_get_be32 (f);
51686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->queue.wptr=qemu_get_be32 (f);
51786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->queue.count=qemu_get_be32 (f);
51886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
51986797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
52086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
52186797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void ps2_kbd_save(QEMUFile* f, void* opaque)
52286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
52386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2KbdState *s = (PS2KbdState*)opaque;
52486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
52586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_common_save (f, &s->common);
52686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32(f, s->scan_enabled);
52786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32(f, s->translate);
52886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32(f, s->scancode_set);
52986797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
53086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
53186797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void ps2_mouse_save(QEMUFile* f, void* opaque)
53286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
53386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2MouseState *s = (PS2MouseState*)opaque;
53486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
53586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_common_save (f, &s->common);
53686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->mouse_status);
53786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->mouse_resolution);
53886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->mouse_sample_rate);
53986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->mouse_wrap);
54086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->mouse_type);
54186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->mouse_detect_state);
54286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32(f, s->mouse_dx);
54386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32(f, s->mouse_dy);
54486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32(f, s->mouse_dz);
54586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->mouse_buttons);
54686797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
54786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
54886797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
54986797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
55086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2KbdState *s = (PS2KbdState*)opaque;
55186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
55286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (version_id != 2 && version_id != 3)
55386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return -EINVAL;
55486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
55586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_common_load (f, &s->common);
55686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->scan_enabled=qemu_get_be32(f);
55786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->translate=qemu_get_be32(f);
55886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (version_id == 3)
55986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->scancode_set=qemu_get_be32(f);
56086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    else
56186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->scancode_set=2;
56286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return 0;
56386797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
56486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
56586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
56686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
56786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2MouseState *s = (PS2MouseState*)opaque;
56886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
56986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (version_id != 2)
57086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return -EINVAL;
57186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
57286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_common_load (f, &s->common);
57386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->mouse_status);
57486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->mouse_resolution);
57586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->mouse_sample_rate);
57686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->mouse_wrap);
57786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->mouse_type);
57886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->mouse_detect_state);
57986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mouse_dx=qemu_get_be32(f);
58086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mouse_dy=qemu_get_be32(f);
58186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mouse_dz=qemu_get_be32(f);
58286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->mouse_buttons);
58386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return 0;
58486797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
58586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
58686797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
58786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
58886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
58986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
59086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->common.update_irq = update_irq;
59186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->common.update_arg = update_arg;
59286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->scancode_set = 2;
59386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_reset(&s->common);
59486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
59586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    //qemu_add_kbd_event_handler(ps2_put_keycode, s);
59686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_register_reset(ps2_reset, 0, &s->common);
59786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return s;
59886797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
59986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
60086797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
60186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
60286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
60386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
60486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->common.update_irq = update_irq;
60586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->common.update_arg = update_arg;
60686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ps2_reset(&s->common);
60786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
60886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    //qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
60986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_register_reset(ps2_reset, 0, &s->common);
61086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return s;
61186797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
612