10e43e99cSbellard /* 20e43e99cSbellard * QEMU PS/2 keyboard/mouse emulation 30e43e99cSbellard * 40e43e99cSbellard * Copyright (c) 2003 Fabrice Bellard 50e43e99cSbellard * 60e43e99cSbellard * Permission is hereby granted, free of charge, to any person obtaining a copy 70e43e99cSbellard * of this software and associated documentation files (the "Software"), to deal 80e43e99cSbellard * in the Software without restriction, including without limitation the rights 90e43e99cSbellard * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 100e43e99cSbellard * copies of the Software, and to permit persons to whom the Software is 110e43e99cSbellard * furnished to do so, subject to the following conditions: 120e43e99cSbellard * 130e43e99cSbellard * The above copyright notice and this permission notice shall be included in 140e43e99cSbellard * all copies or substantial portions of the Software. 150e43e99cSbellard * 160e43e99cSbellard * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 170e43e99cSbellard * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 180e43e99cSbellard * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 190e43e99cSbellard * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 200e43e99cSbellard * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 210e43e99cSbellard * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 220e43e99cSbellard * THE SOFTWARE. 230e43e99cSbellard */ 240430891cSPeter Maydell #include "qemu/osdep.h" 25*ec044a80SHervé Poussineau #include "qemu/log.h" 2683c9f4caSPaolo Bonzini #include "hw/hw.h" 270d09e41aSPaolo Bonzini #include "hw/input/ps2.h" 2828ecbaeeSPaolo Bonzini #include "ui/console.h" 2966e6536eSGerd Hoffmann #include "ui/input.h" 309c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 310e43e99cSbellard 325edab03dSDon Koch #include "trace.h" 335edab03dSDon Koch 340e43e99cSbellard /* debug PC keyboard */ 350e43e99cSbellard //#define DEBUG_KBD 360e43e99cSbellard 370e43e99cSbellard /* debug PC keyboard : only mouse */ 380e43e99cSbellard //#define DEBUG_MOUSE 390e43e99cSbellard 400e43e99cSbellard /* Keyboard Commands */ 410e43e99cSbellard #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ 420e43e99cSbellard #define KBD_CMD_ECHO 0xEE 43e7d93956Saurel32 #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */ 440e43e99cSbellard #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */ 450e43e99cSbellard #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ 460e43e99cSbellard #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ 470e43e99cSbellard #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */ 480e43e99cSbellard #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */ 490e43e99cSbellard #define KBD_CMD_RESET 0xFF /* Reset */ 500e43e99cSbellard 510e43e99cSbellard /* Keyboard Replies */ 520e43e99cSbellard #define KBD_REPLY_POR 0xAA /* Power on reset */ 5335c4d671Saurel32 #define KBD_REPLY_ID 0xAB /* Keyboard ID */ 540e43e99cSbellard #define KBD_REPLY_ACK 0xFA /* Command ACK */ 550e43e99cSbellard #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ 560e43e99cSbellard 570e43e99cSbellard /* Mouse Commands */ 580e43e99cSbellard #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ 590e43e99cSbellard #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ 600e43e99cSbellard #define AUX_SET_RES 0xE8 /* Set resolution */ 610e43e99cSbellard #define AUX_GET_SCALE 0xE9 /* Get scaling factor */ 620e43e99cSbellard #define AUX_SET_STREAM 0xEA /* Set stream mode */ 630e43e99cSbellard #define AUX_POLL 0xEB /* Poll */ 640e43e99cSbellard #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */ 650e43e99cSbellard #define AUX_SET_WRAP 0xEE /* Set wrap mode */ 660e43e99cSbellard #define AUX_SET_REMOTE 0xF0 /* Set remote mode */ 670e43e99cSbellard #define AUX_GET_TYPE 0xF2 /* Get type */ 680e43e99cSbellard #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ 690e43e99cSbellard #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ 700e43e99cSbellard #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ 710e43e99cSbellard #define AUX_SET_DEFAULT 0xF6 720e43e99cSbellard #define AUX_RESET 0xFF /* Reset aux device */ 730e43e99cSbellard #define AUX_ACK 0xFA /* Command byte ACK. */ 740e43e99cSbellard 750e43e99cSbellard #define MOUSE_STATUS_REMOTE 0x40 760e43e99cSbellard #define MOUSE_STATUS_ENABLED 0x20 770e43e99cSbellard #define MOUSE_STATUS_SCALE21 0x10 780e43e99cSbellard 792858ab09SGonglei #define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */ 800e43e99cSbellard 810e43e99cSbellard typedef struct { 822858ab09SGonglei /* Keep the data array 256 bytes long, which compatibility 832858ab09SGonglei with older qemu versions. */ 842858ab09SGonglei uint8_t data[256]; 850e43e99cSbellard int rptr, wptr, count; 860e43e99cSbellard } PS2Queue; 870e43e99cSbellard 880e43e99cSbellard typedef struct { 890e43e99cSbellard PS2Queue queue; 900e43e99cSbellard int32_t write_cmd; 910e43e99cSbellard void (*update_irq)(void *, int); 920e43e99cSbellard void *update_arg; 930e43e99cSbellard } PS2State; 940e43e99cSbellard 950e43e99cSbellard typedef struct { 960e43e99cSbellard PS2State common; 970e43e99cSbellard int scan_enabled; 98f94f5d71Spbrook int translate; 99e7d93956Saurel32 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */ 1007f540ab5SChristophe Fergeau int ledstate; 10157d5c005SHervé Poussineau bool need_high_bit; 1020e43e99cSbellard } PS2KbdState; 1030e43e99cSbellard 1040e43e99cSbellard typedef struct { 1050e43e99cSbellard PS2State common; 1060e43e99cSbellard uint8_t mouse_status; 1070e43e99cSbellard uint8_t mouse_resolution; 1080e43e99cSbellard uint8_t mouse_sample_rate; 1090e43e99cSbellard uint8_t mouse_wrap; 1100e43e99cSbellard uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */ 1110e43e99cSbellard uint8_t mouse_detect_state; 1120e43e99cSbellard int mouse_dx; /* current values, needed for 'poll' mode */ 1130e43e99cSbellard int mouse_dy; 1140e43e99cSbellard int mouse_dz; 1150e43e99cSbellard uint8_t mouse_buttons; 1160e43e99cSbellard } PS2MouseState; 1170e43e99cSbellard 1188c10e0baSHervé Poussineau /* Table to convert from QEMU codes to scancodes. */ 1198c10e0baSHervé Poussineau static const uint16_t qcode_to_keycode_set1[Q_KEY_CODE__MAX] = { 1208c10e0baSHervé Poussineau [0 ... Q_KEY_CODE__MAX - 1] = 0, 1218c10e0baSHervé Poussineau 1228c10e0baSHervé Poussineau [Q_KEY_CODE_A] = 0x1e, 1238c10e0baSHervé Poussineau [Q_KEY_CODE_B] = 0x30, 1248c10e0baSHervé Poussineau [Q_KEY_CODE_C] = 0x2e, 1258c10e0baSHervé Poussineau [Q_KEY_CODE_D] = 0x20, 1268c10e0baSHervé Poussineau [Q_KEY_CODE_E] = 0x12, 1278c10e0baSHervé Poussineau [Q_KEY_CODE_F] = 0x21, 1288c10e0baSHervé Poussineau [Q_KEY_CODE_G] = 0x22, 1298c10e0baSHervé Poussineau [Q_KEY_CODE_H] = 0x23, 1308c10e0baSHervé Poussineau [Q_KEY_CODE_I] = 0x17, 1318c10e0baSHervé Poussineau [Q_KEY_CODE_J] = 0x24, 1328c10e0baSHervé Poussineau [Q_KEY_CODE_K] = 0x25, 1338c10e0baSHervé Poussineau [Q_KEY_CODE_L] = 0x26, 1348c10e0baSHervé Poussineau [Q_KEY_CODE_M] = 0x32, 1358c10e0baSHervé Poussineau [Q_KEY_CODE_N] = 0x31, 1368c10e0baSHervé Poussineau [Q_KEY_CODE_O] = 0x18, 1378c10e0baSHervé Poussineau [Q_KEY_CODE_P] = 0x19, 1388c10e0baSHervé Poussineau [Q_KEY_CODE_Q] = 0x10, 1398c10e0baSHervé Poussineau [Q_KEY_CODE_R] = 0x13, 1408c10e0baSHervé Poussineau [Q_KEY_CODE_S] = 0x1f, 1418c10e0baSHervé Poussineau [Q_KEY_CODE_T] = 0x14, 1428c10e0baSHervé Poussineau [Q_KEY_CODE_U] = 0x16, 1438c10e0baSHervé Poussineau [Q_KEY_CODE_V] = 0x2f, 1448c10e0baSHervé Poussineau [Q_KEY_CODE_W] = 0x11, 1458c10e0baSHervé Poussineau [Q_KEY_CODE_X] = 0x2d, 1468c10e0baSHervé Poussineau [Q_KEY_CODE_Y] = 0x15, 1478c10e0baSHervé Poussineau [Q_KEY_CODE_Z] = 0x2c, 1488c10e0baSHervé Poussineau [Q_KEY_CODE_0] = 0x0b, 1498c10e0baSHervé Poussineau [Q_KEY_CODE_1] = 0x02, 1508c10e0baSHervé Poussineau [Q_KEY_CODE_2] = 0x03, 1518c10e0baSHervé Poussineau [Q_KEY_CODE_3] = 0x04, 1528c10e0baSHervé Poussineau [Q_KEY_CODE_4] = 0x05, 1538c10e0baSHervé Poussineau [Q_KEY_CODE_5] = 0x06, 1548c10e0baSHervé Poussineau [Q_KEY_CODE_6] = 0x07, 1558c10e0baSHervé Poussineau [Q_KEY_CODE_7] = 0x08, 1568c10e0baSHervé Poussineau [Q_KEY_CODE_8] = 0x09, 1578c10e0baSHervé Poussineau [Q_KEY_CODE_9] = 0x0a, 1588c10e0baSHervé Poussineau [Q_KEY_CODE_GRAVE_ACCENT] = 0x29, 1598c10e0baSHervé Poussineau [Q_KEY_CODE_MINUS] = 0x0c, 1608c10e0baSHervé Poussineau [Q_KEY_CODE_EQUAL] = 0x0d, 1618c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSLASH] = 0x2b, 1628c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSPACE] = 0x0e, 1638c10e0baSHervé Poussineau [Q_KEY_CODE_SPC] = 0x39, 1648c10e0baSHervé Poussineau [Q_KEY_CODE_TAB] = 0x0f, 1658c10e0baSHervé Poussineau [Q_KEY_CODE_CAPS_LOCK] = 0x3a, 1668c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT] = 0x2a, 1678c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL] = 0x1d, 1688c10e0baSHervé Poussineau [Q_KEY_CODE_META_L] = 0xe05b, 1698c10e0baSHervé Poussineau [Q_KEY_CODE_ALT] = 0x38, 1708c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT_R] = 0x36, 1718c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL_R] = 0xe01d, 1728c10e0baSHervé Poussineau [Q_KEY_CODE_META_R] = 0xe05c, 1738c10e0baSHervé Poussineau [Q_KEY_CODE_ALT_R] = 0xe038, 1748c10e0baSHervé Poussineau [Q_KEY_CODE_MENU] = 0xe05d, 1758c10e0baSHervé Poussineau [Q_KEY_CODE_RET] = 0x1c, 1768c10e0baSHervé Poussineau [Q_KEY_CODE_ESC] = 0x01, 1778c10e0baSHervé Poussineau [Q_KEY_CODE_F1] = 0x3b, 1788c10e0baSHervé Poussineau [Q_KEY_CODE_F2] = 0x3c, 1798c10e0baSHervé Poussineau [Q_KEY_CODE_F3] = 0x3d, 1808c10e0baSHervé Poussineau [Q_KEY_CODE_F4] = 0x3e, 1818c10e0baSHervé Poussineau [Q_KEY_CODE_F5] = 0x3f, 1828c10e0baSHervé Poussineau [Q_KEY_CODE_F6] = 0x40, 1838c10e0baSHervé Poussineau [Q_KEY_CODE_F7] = 0x41, 1848c10e0baSHervé Poussineau [Q_KEY_CODE_F8] = 0x42, 1858c10e0baSHervé Poussineau [Q_KEY_CODE_F9] = 0x43, 1868c10e0baSHervé Poussineau [Q_KEY_CODE_F10] = 0x44, 1878c10e0baSHervé Poussineau [Q_KEY_CODE_F11] = 0x57, 1888c10e0baSHervé Poussineau [Q_KEY_CODE_F12] = 0x58, 1898c10e0baSHervé Poussineau /* special handling for Q_KEY_CODE_PRINT */ 1908c10e0baSHervé Poussineau [Q_KEY_CODE_SCROLL_LOCK] = 0x46, 1918c10e0baSHervé Poussineau /* special handling for Q_KEY_CODE_PAUSE */ 1928c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_LEFT] = 0x1a, 1938c10e0baSHervé Poussineau [Q_KEY_CODE_INSERT] = 0xe052, 1948c10e0baSHervé Poussineau [Q_KEY_CODE_HOME] = 0xe047, 1958c10e0baSHervé Poussineau [Q_KEY_CODE_PGUP] = 0xe049, 1968c10e0baSHervé Poussineau [Q_KEY_CODE_DELETE] = 0xe053, 1978c10e0baSHervé Poussineau [Q_KEY_CODE_END] = 0xe04f, 1988c10e0baSHervé Poussineau [Q_KEY_CODE_PGDN] = 0xe051, 1998c10e0baSHervé Poussineau [Q_KEY_CODE_UP] = 0xe048, 2008c10e0baSHervé Poussineau [Q_KEY_CODE_LEFT] = 0xe04b, 2018c10e0baSHervé Poussineau [Q_KEY_CODE_DOWN] = 0xe050, 2028c10e0baSHervé Poussineau [Q_KEY_CODE_RIGHT] = 0xe04d, 2038c10e0baSHervé Poussineau [Q_KEY_CODE_NUM_LOCK] = 0x45, 2048c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DIVIDE] = 0xe035, 2058c10e0baSHervé Poussineau [Q_KEY_CODE_KP_MULTIPLY] = 0x37, 2068c10e0baSHervé Poussineau [Q_KEY_CODE_KP_SUBTRACT] = 0x4a, 2078c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ADD] = 0x4e, 2088c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ENTER] = 0xe01c, 2098c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DECIMAL] = 0x53, 2108c10e0baSHervé Poussineau [Q_KEY_CODE_KP_0] = 0x52, 2118c10e0baSHervé Poussineau [Q_KEY_CODE_KP_1] = 0x4f, 2128c10e0baSHervé Poussineau [Q_KEY_CODE_KP_2] = 0x50, 2138c10e0baSHervé Poussineau [Q_KEY_CODE_KP_3] = 0x51, 2148c10e0baSHervé Poussineau [Q_KEY_CODE_KP_4] = 0x4b, 2158c10e0baSHervé Poussineau [Q_KEY_CODE_KP_5] = 0x4c, 2168c10e0baSHervé Poussineau [Q_KEY_CODE_KP_6] = 0x4d, 2178c10e0baSHervé Poussineau [Q_KEY_CODE_KP_7] = 0x47, 2188c10e0baSHervé Poussineau [Q_KEY_CODE_KP_8] = 0x48, 2198c10e0baSHervé Poussineau [Q_KEY_CODE_KP_9] = 0x49, 2208c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b, 2218c10e0baSHervé Poussineau [Q_KEY_CODE_SEMICOLON] = 0x27, 2228c10e0baSHervé Poussineau [Q_KEY_CODE_APOSTROPHE] = 0x28, 2238c10e0baSHervé Poussineau [Q_KEY_CODE_COMMA] = 0x33, 2248c10e0baSHervé Poussineau [Q_KEY_CODE_DOT] = 0x34, 2258c10e0baSHervé Poussineau [Q_KEY_CODE_SLASH] = 0x35, 2268c10e0baSHervé Poussineau 2278c10e0baSHervé Poussineau #if 0 2288c10e0baSHervé Poussineau [Q_KEY_CODE_POWER] = 0x0e5e, 2298c10e0baSHervé Poussineau [Q_KEY_CODE_SLEEP] = 0x0e5f, 2308c10e0baSHervé Poussineau [Q_KEY_CODE_WAKE] = 0x0e63, 2318c10e0baSHervé Poussineau 2328c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIONEXT] = 0xe019, 2338c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOPREV] = 0xe010, 2348c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOSTOP] = 0xe024, 2358c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOPLAY] = 0xe022, 2368c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOMUTE] = 0xe020, 2378c10e0baSHervé Poussineau [Q_KEY_CODE_VOLUMEUP] = 0xe030, 2388c10e0baSHervé Poussineau [Q_KEY_CODE_VOLUMEDOWN] = 0xe02e, 2398c10e0baSHervé Poussineau [Q_KEY_CODE_MEDIASELECT] = 0xe06d, 2408c10e0baSHervé Poussineau [Q_KEY_CODE_MAIL] = 0xe06c, 2418c10e0baSHervé Poussineau [Q_KEY_CODE_CALCULATOR] = 0xe021, 2428c10e0baSHervé Poussineau [Q_KEY_CODE_COMPUTER] = 0xe06b, 2438c10e0baSHervé Poussineau [Q_KEY_CODE_AC_SEARCH] = 0xe065, 2448c10e0baSHervé Poussineau [Q_KEY_CODE_AC_HOME] = 0xe032, 2458c10e0baSHervé Poussineau [Q_KEY_CODE_AC_BACK] = 0xe06a, 2468c10e0baSHervé Poussineau [Q_KEY_CODE_AC_FORWARD] = 0xe069, 2478c10e0baSHervé Poussineau [Q_KEY_CODE_AC_STOP] = 0xe068, 2488c10e0baSHervé Poussineau [Q_KEY_CODE_AC_REFRESH] = 0xe067, 2498c10e0baSHervé Poussineau [Q_KEY_CODE_AC_BOOKMARKS] = 0xe066, 2508c10e0baSHervé Poussineau #endif 2518c10e0baSHervé Poussineau 2528c10e0baSHervé Poussineau [Q_KEY_CODE_ASTERISK] = 0x37, 2538c10e0baSHervé Poussineau [Q_KEY_CODE_LESS] = 0x56, 2548c10e0baSHervé Poussineau [Q_KEY_CODE_RO] = 0x73, 2558c10e0baSHervé Poussineau [Q_KEY_CODE_KP_COMMA] = 0x7e, 256f94f5d71Spbrook }; 2578c10e0baSHervé Poussineau 2588c10e0baSHervé Poussineau static const uint16_t qcode_to_keycode_set2[Q_KEY_CODE__MAX] = { 2598c10e0baSHervé Poussineau [0 ... Q_KEY_CODE__MAX - 1] = 0, 2608c10e0baSHervé Poussineau 2618c10e0baSHervé Poussineau [Q_KEY_CODE_A] = 0x1c, 2628c10e0baSHervé Poussineau [Q_KEY_CODE_B] = 0x32, 2638c10e0baSHervé Poussineau [Q_KEY_CODE_C] = 0x21, 2648c10e0baSHervé Poussineau [Q_KEY_CODE_D] = 0x23, 2658c10e0baSHervé Poussineau [Q_KEY_CODE_E] = 0x24, 2668c10e0baSHervé Poussineau [Q_KEY_CODE_F] = 0x2b, 2678c10e0baSHervé Poussineau [Q_KEY_CODE_G] = 0x34, 2688c10e0baSHervé Poussineau [Q_KEY_CODE_H] = 0x33, 2698c10e0baSHervé Poussineau [Q_KEY_CODE_I] = 0x43, 2708c10e0baSHervé Poussineau [Q_KEY_CODE_J] = 0x3b, 2718c10e0baSHervé Poussineau [Q_KEY_CODE_K] = 0x42, 2728c10e0baSHervé Poussineau [Q_KEY_CODE_L] = 0x4b, 2738c10e0baSHervé Poussineau [Q_KEY_CODE_M] = 0x3a, 2748c10e0baSHervé Poussineau [Q_KEY_CODE_N] = 0x31, 2758c10e0baSHervé Poussineau [Q_KEY_CODE_O] = 0x44, 2768c10e0baSHervé Poussineau [Q_KEY_CODE_P] = 0x4d, 2778c10e0baSHervé Poussineau [Q_KEY_CODE_Q] = 0x15, 2788c10e0baSHervé Poussineau [Q_KEY_CODE_R] = 0x2d, 2798c10e0baSHervé Poussineau [Q_KEY_CODE_S] = 0x1b, 2808c10e0baSHervé Poussineau [Q_KEY_CODE_T] = 0x2c, 2818c10e0baSHervé Poussineau [Q_KEY_CODE_U] = 0x3c, 2828c10e0baSHervé Poussineau [Q_KEY_CODE_V] = 0x2a, 2838c10e0baSHervé Poussineau [Q_KEY_CODE_W] = 0x1d, 2848c10e0baSHervé Poussineau [Q_KEY_CODE_X] = 0x22, 2858c10e0baSHervé Poussineau [Q_KEY_CODE_Y] = 0x35, 2868c10e0baSHervé Poussineau [Q_KEY_CODE_Z] = 0x1a, 2878c10e0baSHervé Poussineau [Q_KEY_CODE_0] = 0x45, 2888c10e0baSHervé Poussineau [Q_KEY_CODE_1] = 0x16, 2898c10e0baSHervé Poussineau [Q_KEY_CODE_2] = 0x1e, 2908c10e0baSHervé Poussineau [Q_KEY_CODE_3] = 0x26, 2918c10e0baSHervé Poussineau [Q_KEY_CODE_4] = 0x25, 2928c10e0baSHervé Poussineau [Q_KEY_CODE_5] = 0x2e, 2938c10e0baSHervé Poussineau [Q_KEY_CODE_6] = 0x36, 2948c10e0baSHervé Poussineau [Q_KEY_CODE_7] = 0x3d, 2958c10e0baSHervé Poussineau [Q_KEY_CODE_8] = 0x3e, 2968c10e0baSHervé Poussineau [Q_KEY_CODE_9] = 0x46, 2978c10e0baSHervé Poussineau [Q_KEY_CODE_GRAVE_ACCENT] = 0x0e, 2988c10e0baSHervé Poussineau [Q_KEY_CODE_MINUS] = 0x4e, 2998c10e0baSHervé Poussineau [Q_KEY_CODE_EQUAL] = 0x55, 3008c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSLASH] = 0x5d, 3018c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSPACE] = 0x66, 3028c10e0baSHervé Poussineau [Q_KEY_CODE_SPC] = 0x29, 3038c10e0baSHervé Poussineau [Q_KEY_CODE_TAB] = 0x0d, 3048c10e0baSHervé Poussineau [Q_KEY_CODE_CAPS_LOCK] = 0x58, 3058c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT] = 0x12, 3068c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL] = 0x14, 3078c10e0baSHervé Poussineau [Q_KEY_CODE_META_L] = 0xe01f, 3088c10e0baSHervé Poussineau [Q_KEY_CODE_ALT] = 0x11, 3098c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT_R] = 0x59, 3108c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL_R] = 0xe014, 3118c10e0baSHervé Poussineau [Q_KEY_CODE_META_R] = 0xe027, 3128c10e0baSHervé Poussineau [Q_KEY_CODE_ALT_R] = 0xe011, 3138c10e0baSHervé Poussineau [Q_KEY_CODE_MENU] = 0xe02f, 3148c10e0baSHervé Poussineau [Q_KEY_CODE_RET] = 0x5a, 3158c10e0baSHervé Poussineau [Q_KEY_CODE_ESC] = 0x76, 3168c10e0baSHervé Poussineau [Q_KEY_CODE_F1] = 0x05, 3178c10e0baSHervé Poussineau [Q_KEY_CODE_F2] = 0x06, 3188c10e0baSHervé Poussineau [Q_KEY_CODE_F3] = 0x04, 3198c10e0baSHervé Poussineau [Q_KEY_CODE_F4] = 0x0c, 3208c10e0baSHervé Poussineau [Q_KEY_CODE_F5] = 0x03, 3218c10e0baSHervé Poussineau [Q_KEY_CODE_F6] = 0x0b, 3228c10e0baSHervé Poussineau [Q_KEY_CODE_F7] = 0x83, 3238c10e0baSHervé Poussineau [Q_KEY_CODE_F8] = 0x0a, 3248c10e0baSHervé Poussineau [Q_KEY_CODE_F9] = 0x01, 3258c10e0baSHervé Poussineau [Q_KEY_CODE_F10] = 0x09, 3268c10e0baSHervé Poussineau [Q_KEY_CODE_F11] = 0x78, 3278c10e0baSHervé Poussineau [Q_KEY_CODE_F12] = 0x07, 3288c10e0baSHervé Poussineau /* special handling for Q_KEY_CODE_PRINT */ 3298c10e0baSHervé Poussineau [Q_KEY_CODE_SCROLL_LOCK] = 0x7e, 3308c10e0baSHervé Poussineau /* special handling for Q_KEY_CODE_PAUSE */ 3318c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_LEFT] = 0x54, 3328c10e0baSHervé Poussineau [Q_KEY_CODE_INSERT] = 0xe070, 3338c10e0baSHervé Poussineau [Q_KEY_CODE_HOME] = 0xe06c, 3348c10e0baSHervé Poussineau [Q_KEY_CODE_PGUP] = 0xe07d, 3358c10e0baSHervé Poussineau [Q_KEY_CODE_DELETE] = 0xe071, 3368c10e0baSHervé Poussineau [Q_KEY_CODE_END] = 0xe069, 3378c10e0baSHervé Poussineau [Q_KEY_CODE_PGDN] = 0xe07a, 3388c10e0baSHervé Poussineau [Q_KEY_CODE_UP] = 0xe075, 3398c10e0baSHervé Poussineau [Q_KEY_CODE_LEFT] = 0xe06b, 3408c10e0baSHervé Poussineau [Q_KEY_CODE_DOWN] = 0xe072, 3418c10e0baSHervé Poussineau [Q_KEY_CODE_RIGHT] = 0xe074, 3428c10e0baSHervé Poussineau [Q_KEY_CODE_NUM_LOCK] = 0x77, 3438c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DIVIDE] = 0xe04a, 3448c10e0baSHervé Poussineau [Q_KEY_CODE_KP_MULTIPLY] = 0x7c, 3458c10e0baSHervé Poussineau [Q_KEY_CODE_KP_SUBTRACT] = 0x7b, 3468c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ADD] = 0x79, 3478c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ENTER] = 0xe05a, 3488c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DECIMAL] = 0x71, 3498c10e0baSHervé Poussineau [Q_KEY_CODE_KP_0] = 0x70, 3508c10e0baSHervé Poussineau [Q_KEY_CODE_KP_1] = 0x69, 3518c10e0baSHervé Poussineau [Q_KEY_CODE_KP_2] = 0x72, 3528c10e0baSHervé Poussineau [Q_KEY_CODE_KP_3] = 0x7a, 3538c10e0baSHervé Poussineau [Q_KEY_CODE_KP_4] = 0x6b, 3548c10e0baSHervé Poussineau [Q_KEY_CODE_KP_5] = 0x73, 3558c10e0baSHervé Poussineau [Q_KEY_CODE_KP_6] = 0x74, 3568c10e0baSHervé Poussineau [Q_KEY_CODE_KP_7] = 0x6c, 3578c10e0baSHervé Poussineau [Q_KEY_CODE_KP_8] = 0x75, 3588c10e0baSHervé Poussineau [Q_KEY_CODE_KP_9] = 0x7d, 3598c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_RIGHT] = 0x5b, 3608c10e0baSHervé Poussineau [Q_KEY_CODE_SEMICOLON] = 0x4c, 3618c10e0baSHervé Poussineau [Q_KEY_CODE_APOSTROPHE] = 0x52, 3628c10e0baSHervé Poussineau [Q_KEY_CODE_COMMA] = 0x41, 3638c10e0baSHervé Poussineau [Q_KEY_CODE_DOT] = 0x49, 3648c10e0baSHervé Poussineau [Q_KEY_CODE_SLASH] = 0x4a, 3658c10e0baSHervé Poussineau 3668c10e0baSHervé Poussineau #if 0 3678c10e0baSHervé Poussineau [Q_KEY_CODE_POWER] = 0x0e37, 3688c10e0baSHervé Poussineau [Q_KEY_CODE_SLEEP] = 0x0e3f, 3698c10e0baSHervé Poussineau [Q_KEY_CODE_WAKE] = 0x0e5e, 3708c10e0baSHervé Poussineau 3718c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIONEXT] = 0xe04d, 3728c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOPREV] = 0xe015, 3738c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOSTOP] = 0xe03b, 3748c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOPLAY] = 0xe034, 3758c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOMUTE] = 0xe023, 3768c10e0baSHervé Poussineau [Q_KEY_CODE_VOLUMEUP] = 0xe032, 3778c10e0baSHervé Poussineau [Q_KEY_CODE_VOLUMEDOWN] = 0xe021, 3788c10e0baSHervé Poussineau [Q_KEY_CODE_MEDIASELECT] = 0xe050, 3798c10e0baSHervé Poussineau [Q_KEY_CODE_MAIL] = 0xe048, 3808c10e0baSHervé Poussineau [Q_KEY_CODE_CALCULATOR] = 0xe02b, 3818c10e0baSHervé Poussineau [Q_KEY_CODE_COMPUTER] = 0xe040, 3828c10e0baSHervé Poussineau [Q_KEY_CODE_AC_SEARCH] = 0xe010, 3838c10e0baSHervé Poussineau [Q_KEY_CODE_AC_HOME] = 0xe03a, 3848c10e0baSHervé Poussineau [Q_KEY_CODE_AC_BACK] = 0xe038, 3858c10e0baSHervé Poussineau [Q_KEY_CODE_AC_FORWARD] = 0xe030, 3868c10e0baSHervé Poussineau [Q_KEY_CODE_AC_STOP] = 0xe028, 3878c10e0baSHervé Poussineau [Q_KEY_CODE_AC_REFRESH] = 0xe020, 3888c10e0baSHervé Poussineau [Q_KEY_CODE_AC_BOOKMARKS] = 0xe018, 3898c10e0baSHervé Poussineau #endif 3908c10e0baSHervé Poussineau 3918c10e0baSHervé Poussineau [Q_KEY_CODE_ALTGR] = 0x08, 3928c10e0baSHervé Poussineau [Q_KEY_CODE_ALTGR_R] = 0xe008, 3938c10e0baSHervé Poussineau [Q_KEY_CODE_ASTERISK] = 0x7c, 3948c10e0baSHervé Poussineau [Q_KEY_CODE_LESS] = 0x61, 3958c10e0baSHervé Poussineau [Q_KEY_CODE_SYSRQ] = 0x7f, 3968c10e0baSHervé Poussineau [Q_KEY_CODE_RO] = 0x51, 3978c10e0baSHervé Poussineau [Q_KEY_CODE_KP_COMMA] = 0x6d, 3988c10e0baSHervé Poussineau }; 3998c10e0baSHervé Poussineau 4008c10e0baSHervé Poussineau static const uint16_t qcode_to_keycode_set3[Q_KEY_CODE__MAX] = { 4018c10e0baSHervé Poussineau [0 ... Q_KEY_CODE__MAX - 1] = 0, 4028c10e0baSHervé Poussineau 4038c10e0baSHervé Poussineau [Q_KEY_CODE_A] = 0x1c, 4048c10e0baSHervé Poussineau [Q_KEY_CODE_B] = 0x32, 4058c10e0baSHervé Poussineau [Q_KEY_CODE_C] = 0x21, 4068c10e0baSHervé Poussineau [Q_KEY_CODE_D] = 0x23, 4078c10e0baSHervé Poussineau [Q_KEY_CODE_E] = 0x24, 4088c10e0baSHervé Poussineau [Q_KEY_CODE_F] = 0x2b, 4098c10e0baSHervé Poussineau [Q_KEY_CODE_G] = 0x34, 4108c10e0baSHervé Poussineau [Q_KEY_CODE_H] = 0x33, 4118c10e0baSHervé Poussineau [Q_KEY_CODE_I] = 0x43, 4128c10e0baSHervé Poussineau [Q_KEY_CODE_J] = 0x3b, 4138c10e0baSHervé Poussineau [Q_KEY_CODE_K] = 0x42, 4148c10e0baSHervé Poussineau [Q_KEY_CODE_L] = 0x4b, 4158c10e0baSHervé Poussineau [Q_KEY_CODE_M] = 0x3a, 4168c10e0baSHervé Poussineau [Q_KEY_CODE_N] = 0x31, 4178c10e0baSHervé Poussineau [Q_KEY_CODE_O] = 0x44, 4188c10e0baSHervé Poussineau [Q_KEY_CODE_P] = 0x4d, 4198c10e0baSHervé Poussineau [Q_KEY_CODE_Q] = 0x15, 4208c10e0baSHervé Poussineau [Q_KEY_CODE_R] = 0x2d, 4218c10e0baSHervé Poussineau [Q_KEY_CODE_S] = 0x1b, 4228c10e0baSHervé Poussineau [Q_KEY_CODE_T] = 0x2c, 4238c10e0baSHervé Poussineau [Q_KEY_CODE_U] = 0x3c, 4248c10e0baSHervé Poussineau [Q_KEY_CODE_V] = 0x2a, 4258c10e0baSHervé Poussineau [Q_KEY_CODE_W] = 0x1d, 4268c10e0baSHervé Poussineau [Q_KEY_CODE_X] = 0x22, 4278c10e0baSHervé Poussineau [Q_KEY_CODE_Y] = 0x35, 4288c10e0baSHervé Poussineau [Q_KEY_CODE_Z] = 0x1a, 4298c10e0baSHervé Poussineau [Q_KEY_CODE_0] = 0x45, 4308c10e0baSHervé Poussineau [Q_KEY_CODE_1] = 0x16, 4318c10e0baSHervé Poussineau [Q_KEY_CODE_2] = 0x1e, 4328c10e0baSHervé Poussineau [Q_KEY_CODE_3] = 0x26, 4338c10e0baSHervé Poussineau [Q_KEY_CODE_4] = 0x25, 4348c10e0baSHervé Poussineau [Q_KEY_CODE_5] = 0x2e, 4358c10e0baSHervé Poussineau [Q_KEY_CODE_6] = 0x36, 4368c10e0baSHervé Poussineau [Q_KEY_CODE_7] = 0x3d, 4378c10e0baSHervé Poussineau [Q_KEY_CODE_8] = 0x3e, 4388c10e0baSHervé Poussineau [Q_KEY_CODE_9] = 0x46, 4398c10e0baSHervé Poussineau [Q_KEY_CODE_GRAVE_ACCENT] = 0x0e, 4408c10e0baSHervé Poussineau [Q_KEY_CODE_MINUS] = 0x4e, 4418c10e0baSHervé Poussineau [Q_KEY_CODE_EQUAL] = 0x55, 4428c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSLASH] = 0x5c, 4438c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSPACE] = 0x66, 4448c10e0baSHervé Poussineau [Q_KEY_CODE_SPC] = 0x29, 4458c10e0baSHervé Poussineau [Q_KEY_CODE_TAB] = 0x0d, 4468c10e0baSHervé Poussineau [Q_KEY_CODE_CAPS_LOCK] = 0x14, 4478c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT] = 0x12, 4488c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL] = 0x11, 4498c10e0baSHervé Poussineau [Q_KEY_CODE_META_L] = 0x8b, 4508c10e0baSHervé Poussineau [Q_KEY_CODE_ALT] = 0x19, 4518c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT_R] = 0x59, 4528c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL_R] = 0x58, 4538c10e0baSHervé Poussineau [Q_KEY_CODE_META_R] = 0x8c, 4548c10e0baSHervé Poussineau [Q_KEY_CODE_ALT_R] = 0x39, 4558c10e0baSHervé Poussineau [Q_KEY_CODE_MENU] = 0x8d, 4568c10e0baSHervé Poussineau [Q_KEY_CODE_RET] = 0x5a, 4578c10e0baSHervé Poussineau [Q_KEY_CODE_ESC] = 0x08, 4588c10e0baSHervé Poussineau [Q_KEY_CODE_F1] = 0x07, 4598c10e0baSHervé Poussineau [Q_KEY_CODE_F2] = 0x0f, 4608c10e0baSHervé Poussineau [Q_KEY_CODE_F3] = 0x17, 4618c10e0baSHervé Poussineau [Q_KEY_CODE_F4] = 0x1f, 4628c10e0baSHervé Poussineau [Q_KEY_CODE_F5] = 0x27, 4638c10e0baSHervé Poussineau [Q_KEY_CODE_F6] = 0x2f, 4648c10e0baSHervé Poussineau [Q_KEY_CODE_F7] = 0x37, 4658c10e0baSHervé Poussineau [Q_KEY_CODE_F8] = 0x3f, 4668c10e0baSHervé Poussineau [Q_KEY_CODE_F9] = 0x47, 4678c10e0baSHervé Poussineau [Q_KEY_CODE_F10] = 0x4f, 4688c10e0baSHervé Poussineau [Q_KEY_CODE_F11] = 0x56, 4698c10e0baSHervé Poussineau [Q_KEY_CODE_F12] = 0x5e, 4708c10e0baSHervé Poussineau [Q_KEY_CODE_PRINT] = 0x57, 4718c10e0baSHervé Poussineau [Q_KEY_CODE_SCROLL_LOCK] = 0x5f, 4728c10e0baSHervé Poussineau [Q_KEY_CODE_PAUSE] = 0x62, 4738c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_LEFT] = 0x54, 4748c10e0baSHervé Poussineau [Q_KEY_CODE_INSERT] = 0x67, 4758c10e0baSHervé Poussineau [Q_KEY_CODE_HOME] = 0x6e, 4768c10e0baSHervé Poussineau [Q_KEY_CODE_PGUP] = 0x6f, 4778c10e0baSHervé Poussineau [Q_KEY_CODE_DELETE] = 0x64, 4788c10e0baSHervé Poussineau [Q_KEY_CODE_END] = 0x65, 4798c10e0baSHervé Poussineau [Q_KEY_CODE_PGDN] = 0x6d, 4808c10e0baSHervé Poussineau [Q_KEY_CODE_UP] = 0x63, 4818c10e0baSHervé Poussineau [Q_KEY_CODE_LEFT] = 0x61, 4828c10e0baSHervé Poussineau [Q_KEY_CODE_DOWN] = 0x60, 4838c10e0baSHervé Poussineau [Q_KEY_CODE_RIGHT] = 0x6a, 4848c10e0baSHervé Poussineau [Q_KEY_CODE_NUM_LOCK] = 0x76, 4858c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DIVIDE] = 0x4a, 4868c10e0baSHervé Poussineau [Q_KEY_CODE_KP_MULTIPLY] = 0x7e, 4878c10e0baSHervé Poussineau [Q_KEY_CODE_KP_SUBTRACT] = 0x4e, 4888c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ADD] = 0x7c, 4898c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ENTER] = 0x79, 4908c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DECIMAL] = 0x71, 4918c10e0baSHervé Poussineau [Q_KEY_CODE_KP_0] = 0x70, 4928c10e0baSHervé Poussineau [Q_KEY_CODE_KP_1] = 0x69, 4938c10e0baSHervé Poussineau [Q_KEY_CODE_KP_2] = 0x72, 4948c10e0baSHervé Poussineau [Q_KEY_CODE_KP_3] = 0x7a, 4958c10e0baSHervé Poussineau [Q_KEY_CODE_KP_4] = 0x6b, 4968c10e0baSHervé Poussineau [Q_KEY_CODE_KP_5] = 0x73, 4978c10e0baSHervé Poussineau [Q_KEY_CODE_KP_6] = 0x74, 4988c10e0baSHervé Poussineau [Q_KEY_CODE_KP_7] = 0x6c, 4998c10e0baSHervé Poussineau [Q_KEY_CODE_KP_8] = 0x75, 5008c10e0baSHervé Poussineau [Q_KEY_CODE_KP_9] = 0x7d, 5018c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_RIGHT] = 0x5b, 5028c10e0baSHervé Poussineau [Q_KEY_CODE_SEMICOLON] = 0x4c, 5038c10e0baSHervé Poussineau [Q_KEY_CODE_APOSTROPHE] = 0x52, 5048c10e0baSHervé Poussineau [Q_KEY_CODE_COMMA] = 0x41, 5058c10e0baSHervé Poussineau [Q_KEY_CODE_DOT] = 0x49, 5068c10e0baSHervé Poussineau [Q_KEY_CODE_SLASH] = 0x4a, 5077096a96dSRoy Tam }; 508f94f5d71Spbrook 50957d5c005SHervé Poussineau static uint8_t translate_table[256] = { 51057d5c005SHervé Poussineau 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 51157d5c005SHervé Poussineau 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, 51257d5c005SHervé Poussineau 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, 51357d5c005SHervé Poussineau 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, 51457d5c005SHervé Poussineau 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, 51557d5c005SHervé Poussineau 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, 51657d5c005SHervé Poussineau 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, 51757d5c005SHervé Poussineau 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, 51857d5c005SHervé Poussineau 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, 51957d5c005SHervé Poussineau 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, 52057d5c005SHervé Poussineau 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, 52157d5c005SHervé Poussineau 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, 52257d5c005SHervé Poussineau 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, 52357d5c005SHervé Poussineau 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, 52457d5c005SHervé Poussineau 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, 52557d5c005SHervé Poussineau 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, 52657d5c005SHervé Poussineau 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, 52757d5c005SHervé Poussineau 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 52857d5c005SHervé Poussineau 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 52957d5c005SHervé Poussineau 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 53057d5c005SHervé Poussineau 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 53157d5c005SHervé Poussineau 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 53257d5c005SHervé Poussineau 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 53357d5c005SHervé Poussineau 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 53457d5c005SHervé Poussineau 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 53557d5c005SHervé Poussineau 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 53657d5c005SHervé Poussineau 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 53757d5c005SHervé Poussineau 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 53857d5c005SHervé Poussineau 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 53957d5c005SHervé Poussineau 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 54057d5c005SHervé Poussineau 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 54157d5c005SHervé Poussineau 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 54257d5c005SHervé Poussineau }; 54357d5c005SHervé Poussineau 5440e43e99cSbellard void ps2_queue(void *opaque, int b) 5450e43e99cSbellard { 5460e43e99cSbellard PS2State *s = (PS2State *)opaque; 5470e43e99cSbellard PS2Queue *q = &s->queue; 5480e43e99cSbellard 5492858ab09SGonglei if (q->count >= PS2_QUEUE_SIZE - 1) 5500e43e99cSbellard return; 5510e43e99cSbellard q->data[q->wptr] = b; 5520e43e99cSbellard if (++q->wptr == PS2_QUEUE_SIZE) 5530e43e99cSbellard q->wptr = 0; 5540e43e99cSbellard q->count++; 5550e43e99cSbellard s->update_irq(s->update_arg, 1); 5560e43e99cSbellard } 5570e43e99cSbellard 55857d5c005SHervé Poussineau /* keycode is the untranslated scancode in the current scancode set. */ 5590e43e99cSbellard static void ps2_put_keycode(void *opaque, int keycode) 5600e43e99cSbellard { 561f94f5d71Spbrook PS2KbdState *s = opaque; 562e7d93956Saurel32 5635edab03dSDon Koch trace_ps2_put_keycode(opaque, keycode); 564fd214d18SGerd Hoffmann qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); 56557d5c005SHervé Poussineau 56657d5c005SHervé Poussineau if (s->translate) { 56757d5c005SHervé Poussineau if (keycode == 0xf0) { 56857d5c005SHervé Poussineau s->need_high_bit = true; 56957d5c005SHervé Poussineau } else if (s->need_high_bit) { 57057d5c005SHervé Poussineau ps2_queue(&s->common, translate_table[keycode] | 0x80); 57157d5c005SHervé Poussineau s->need_high_bit = false; 57257d5c005SHervé Poussineau } else { 57357d5c005SHervé Poussineau ps2_queue(&s->common, translate_table[keycode]); 5747096a96dSRoy Tam } 57557d5c005SHervé Poussineau } else { 5760e43e99cSbellard ps2_queue(&s->common, keycode); 5770e43e99cSbellard } 57857d5c005SHervé Poussineau } 5790e43e99cSbellard 58066e6536eSGerd Hoffmann static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src, 58166e6536eSGerd Hoffmann InputEvent *evt) 58266e6536eSGerd Hoffmann { 58366e6536eSGerd Hoffmann PS2KbdState *s = (PS2KbdState *)dev; 58432bafa8fSEric Blake InputKeyEvent *key = evt->u.key.data; 5858c10e0baSHervé Poussineau int qcode; 5868c10e0baSHervé Poussineau uint16_t keycode; 58766e6536eSGerd Hoffmann 58866e6536eSGerd Hoffmann qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); 5898c10e0baSHervé Poussineau assert(evt->type == INPUT_EVENT_KIND_KEY); 5908c10e0baSHervé Poussineau qcode = qemu_input_key_value_to_qcode(key->key); 59157d5c005SHervé Poussineau 5928c10e0baSHervé Poussineau if (s->scancode_set == 1) { 5938c10e0baSHervé Poussineau if (qcode == Q_KEY_CODE_PAUSE) { 5948c10e0baSHervé Poussineau if (key->down) { 5958c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe1); 5968c10e0baSHervé Poussineau ps2_put_keycode(s, 0x1d); 5978c10e0baSHervé Poussineau ps2_put_keycode(s, 0x45); 5988c10e0baSHervé Poussineau ps2_put_keycode(s, 0x91); 5998c10e0baSHervé Poussineau ps2_put_keycode(s, 0x9d); 6008c10e0baSHervé Poussineau ps2_put_keycode(s, 0xc5); 6018c10e0baSHervé Poussineau } 6028c10e0baSHervé Poussineau } else if (qcode == Q_KEY_CODE_PRINT) { 6038c10e0baSHervé Poussineau if (key->down) { 6048c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 6058c10e0baSHervé Poussineau ps2_put_keycode(s, 0x2a); 6068c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 6078c10e0baSHervé Poussineau ps2_put_keycode(s, 0x37); 6088c10e0baSHervé Poussineau } else { 6098c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 6108c10e0baSHervé Poussineau ps2_put_keycode(s, 0xb7); 6118c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 6128c10e0baSHervé Poussineau ps2_put_keycode(s, 0xaa); 6138c10e0baSHervé Poussineau } 6148c10e0baSHervé Poussineau } else { 6158c10e0baSHervé Poussineau keycode = qcode_to_keycode_set1[qcode]; 6168c10e0baSHervé Poussineau if (keycode) { 6178c10e0baSHervé Poussineau if (keycode & 0xff00) { 6188c10e0baSHervé Poussineau ps2_put_keycode(s, keycode >> 8); 6198c10e0baSHervé Poussineau } 6208c10e0baSHervé Poussineau if (!key->down) { 6218c10e0baSHervé Poussineau keycode |= 0x80; 6228c10e0baSHervé Poussineau } 6238c10e0baSHervé Poussineau ps2_put_keycode(s, keycode & 0xff); 6248c10e0baSHervé Poussineau } else { 625*ec044a80SHervé Poussineau qemu_log_mask(LOG_UNIMP, 626*ec044a80SHervé Poussineau "ps2: ignoring key with qcode %d\n", qcode); 6278c10e0baSHervé Poussineau } 6288c10e0baSHervé Poussineau } 6298c10e0baSHervé Poussineau } else if (s->scancode_set == 2) { 6308c10e0baSHervé Poussineau if (qcode == Q_KEY_CODE_PAUSE) { 6318c10e0baSHervé Poussineau if (key->down) { 6328c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe1); 6338c10e0baSHervé Poussineau ps2_put_keycode(s, 0x14); 6348c10e0baSHervé Poussineau ps2_put_keycode(s, 0x77); 6358c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe1); 6368c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 6378c10e0baSHervé Poussineau ps2_put_keycode(s, 0x14); 6388c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 6398c10e0baSHervé Poussineau ps2_put_keycode(s, 0x77); 6408c10e0baSHervé Poussineau } 6418c10e0baSHervé Poussineau } else if (qcode == Q_KEY_CODE_PRINT) { 6428c10e0baSHervé Poussineau if (key->down) { 6438c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 6448c10e0baSHervé Poussineau ps2_put_keycode(s, 0x12); 6458c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 6468c10e0baSHervé Poussineau ps2_put_keycode(s, 0x7c); 6478c10e0baSHervé Poussineau } else { 6488c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 6498c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 6508c10e0baSHervé Poussineau ps2_put_keycode(s, 0x7c); 6518c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 6528c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 6538c10e0baSHervé Poussineau ps2_put_keycode(s, 0x12); 6548c10e0baSHervé Poussineau } 6558c10e0baSHervé Poussineau } else { 6568c10e0baSHervé Poussineau keycode = qcode_to_keycode_set2[qcode]; 6578c10e0baSHervé Poussineau if (keycode) { 6588c10e0baSHervé Poussineau if (keycode & 0xff00) { 6598c10e0baSHervé Poussineau ps2_put_keycode(s, keycode >> 8); 6608c10e0baSHervé Poussineau } 6618c10e0baSHervé Poussineau if (!key->down) { 6628c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 6638c10e0baSHervé Poussineau } 6648c10e0baSHervé Poussineau ps2_put_keycode(s, keycode & 0xff); 66557d5c005SHervé Poussineau } else { 666*ec044a80SHervé Poussineau qemu_log_mask(LOG_UNIMP, 667*ec044a80SHervé Poussineau "ps2: ignoring key with qcode %d\n", qcode); 66857d5c005SHervé Poussineau } 66957d5c005SHervé Poussineau } 67057d5c005SHervé Poussineau } else if (s->scancode_set == 3) { 6718c10e0baSHervé Poussineau keycode = qcode_to_keycode_set3[qcode]; 6728c10e0baSHervé Poussineau if (keycode) { 6738c10e0baSHervé Poussineau /* FIXME: break code should be configured on a key by key basis */ 6748c10e0baSHervé Poussineau if (!key->down) { 6758c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 67657d5c005SHervé Poussineau } 67757d5c005SHervé Poussineau ps2_put_keycode(s, keycode); 6788c10e0baSHervé Poussineau } else { 679*ec044a80SHervé Poussineau qemu_log_mask(LOG_UNIMP, 680*ec044a80SHervé Poussineau "ps2: ignoring key with qcode %d\n", qcode); 6818c10e0baSHervé Poussineau } 68266e6536eSGerd Hoffmann } 68366e6536eSGerd Hoffmann } 68466e6536eSGerd Hoffmann 6850e43e99cSbellard uint32_t ps2_read_data(void *opaque) 6860e43e99cSbellard { 6870e43e99cSbellard PS2State *s = (PS2State *)opaque; 6880e43e99cSbellard PS2Queue *q; 6890e43e99cSbellard int val, index; 6900e43e99cSbellard 6915edab03dSDon Koch trace_ps2_read_data(opaque); 6920e43e99cSbellard q = &s->queue; 6930e43e99cSbellard if (q->count == 0) { 6940e43e99cSbellard /* NOTE: if no data left, we return the last keyboard one 6950e43e99cSbellard (needed for EMM386) */ 6960e43e99cSbellard /* XXX: need a timer to do things correctly */ 6970e43e99cSbellard index = q->rptr - 1; 6980e43e99cSbellard if (index < 0) 6990e43e99cSbellard index = PS2_QUEUE_SIZE - 1; 7000e43e99cSbellard val = q->data[index]; 7010e43e99cSbellard } else { 7020e43e99cSbellard val = q->data[q->rptr]; 7030e43e99cSbellard if (++q->rptr == PS2_QUEUE_SIZE) 7040e43e99cSbellard q->rptr = 0; 7050e43e99cSbellard q->count--; 7060e43e99cSbellard /* reading deasserts IRQ */ 7070e43e99cSbellard s->update_irq(s->update_arg, 0); 7080e43e99cSbellard /* reassert IRQs if data left */ 7090e43e99cSbellard s->update_irq(s->update_arg, q->count != 0); 7100e43e99cSbellard } 7110e43e99cSbellard return val; 7120e43e99cSbellard } 7130e43e99cSbellard 7147f540ab5SChristophe Fergeau static void ps2_set_ledstate(PS2KbdState *s, int ledstate) 7157f540ab5SChristophe Fergeau { 7165edab03dSDon Koch trace_ps2_set_ledstate(s, ledstate); 7177f540ab5SChristophe Fergeau s->ledstate = ledstate; 7187f540ab5SChristophe Fergeau kbd_put_ledstate(ledstate); 7197f540ab5SChristophe Fergeau } 7207f540ab5SChristophe Fergeau 7210e43e99cSbellard static void ps2_reset_keyboard(PS2KbdState *s) 7220e43e99cSbellard { 7235edab03dSDon Koch trace_ps2_reset_keyboard(s); 7240e43e99cSbellard s->scan_enabled = 1; 725e7d93956Saurel32 s->scancode_set = 2; 7267f540ab5SChristophe Fergeau ps2_set_ledstate(s, 0); 7270e43e99cSbellard } 7280e43e99cSbellard 7290e43e99cSbellard void ps2_write_keyboard(void *opaque, int val) 7300e43e99cSbellard { 7310e43e99cSbellard PS2KbdState *s = (PS2KbdState *)opaque; 7320e43e99cSbellard 7335edab03dSDon Koch trace_ps2_write_keyboard(opaque, val); 7340e43e99cSbellard switch(s->common.write_cmd) { 7350e43e99cSbellard default: 7360e43e99cSbellard case -1: 7370e43e99cSbellard switch(val) { 7380e43e99cSbellard case 0x00: 7390e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 7400e43e99cSbellard break; 7410e43e99cSbellard case 0x05: 7420e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_RESEND); 7430e43e99cSbellard break; 7440e43e99cSbellard case KBD_CMD_GET_ID: 7450e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 746e7d93956Saurel32 /* We emulate a MF2 AT keyboard here */ 74735c4d671Saurel32 ps2_queue(&s->common, KBD_REPLY_ID); 74835c4d671Saurel32 if (s->translate) 74935c4d671Saurel32 ps2_queue(&s->common, 0x41); 75035c4d671Saurel32 else 75135c4d671Saurel32 ps2_queue(&s->common, 0x83); 7520e43e99cSbellard break; 7530e43e99cSbellard case KBD_CMD_ECHO: 7540e43e99cSbellard ps2_queue(&s->common, KBD_CMD_ECHO); 7550e43e99cSbellard break; 7560e43e99cSbellard case KBD_CMD_ENABLE: 7570e43e99cSbellard s->scan_enabled = 1; 7580e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 7590e43e99cSbellard break; 760e7d93956Saurel32 case KBD_CMD_SCANCODE: 7610e43e99cSbellard case KBD_CMD_SET_LEDS: 7620e43e99cSbellard case KBD_CMD_SET_RATE: 7630e43e99cSbellard s->common.write_cmd = val; 7640e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 7650e43e99cSbellard break; 7660e43e99cSbellard case KBD_CMD_RESET_DISABLE: 7670e43e99cSbellard ps2_reset_keyboard(s); 7680e43e99cSbellard s->scan_enabled = 0; 7690e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 7700e43e99cSbellard break; 7710e43e99cSbellard case KBD_CMD_RESET_ENABLE: 7720e43e99cSbellard ps2_reset_keyboard(s); 7730e43e99cSbellard s->scan_enabled = 1; 7740e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 7750e43e99cSbellard break; 7760e43e99cSbellard case KBD_CMD_RESET: 7770e43e99cSbellard ps2_reset_keyboard(s); 7780e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 7790e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_POR); 7800e43e99cSbellard break; 7810e43e99cSbellard default: 78206b3611fSHervé Poussineau ps2_queue(&s->common, KBD_REPLY_RESEND); 7830e43e99cSbellard break; 7840e43e99cSbellard } 7850e43e99cSbellard break; 786e7d93956Saurel32 case KBD_CMD_SCANCODE: 787e7d93956Saurel32 if (val == 0) { 7884df23b64SHervé Poussineau ps2_queue(&s->common, KBD_REPLY_ACK); 78957d5c005SHervé Poussineau ps2_put_keycode(s, s->scancode_set); 7904df23b64SHervé Poussineau } else if (val >= 1 && val <= 3) { 791e7d93956Saurel32 s->scancode_set = val; 792e7d93956Saurel32 ps2_queue(&s->common, KBD_REPLY_ACK); 7934df23b64SHervé Poussineau } else { 7944df23b64SHervé Poussineau ps2_queue(&s->common, KBD_REPLY_RESEND); 795e7d93956Saurel32 } 796e7d93956Saurel32 s->common.write_cmd = -1; 797e7d93956Saurel32 break; 7980e43e99cSbellard case KBD_CMD_SET_LEDS: 7997f540ab5SChristophe Fergeau ps2_set_ledstate(s, val); 8000e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 8010e43e99cSbellard s->common.write_cmd = -1; 8020e43e99cSbellard break; 8030e43e99cSbellard case KBD_CMD_SET_RATE: 8040e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 8050e43e99cSbellard s->common.write_cmd = -1; 8060e43e99cSbellard break; 8070e43e99cSbellard } 8080e43e99cSbellard } 8090e43e99cSbellard 810f94f5d71Spbrook /* Set the scancode translation mode. 811f94f5d71Spbrook 0 = raw scancodes. 812f94f5d71Spbrook 1 = translated scancodes (used by qemu internally). */ 813f94f5d71Spbrook 814f94f5d71Spbrook void ps2_keyboard_set_translation(void *opaque, int mode) 815f94f5d71Spbrook { 816f94f5d71Spbrook PS2KbdState *s = (PS2KbdState *)opaque; 8175edab03dSDon Koch trace_ps2_keyboard_set_translation(opaque, mode); 818f94f5d71Spbrook s->translate = mode; 819f94f5d71Spbrook } 820f94f5d71Spbrook 8210e43e99cSbellard static void ps2_mouse_send_packet(PS2MouseState *s) 8220e43e99cSbellard { 8230e43e99cSbellard unsigned int b; 8240e43e99cSbellard int dx1, dy1, dz1; 8250e43e99cSbellard 8260e43e99cSbellard dx1 = s->mouse_dx; 8270e43e99cSbellard dy1 = s->mouse_dy; 8280e43e99cSbellard dz1 = s->mouse_dz; 8290e43e99cSbellard /* XXX: increase range to 8 bits ? */ 8300e43e99cSbellard if (dx1 > 127) 8310e43e99cSbellard dx1 = 127; 8320e43e99cSbellard else if (dx1 < -127) 8330e43e99cSbellard dx1 = -127; 8340e43e99cSbellard if (dy1 > 127) 8350e43e99cSbellard dy1 = 127; 8360e43e99cSbellard else if (dy1 < -127) 8370e43e99cSbellard dy1 = -127; 8380e43e99cSbellard b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); 8390e43e99cSbellard ps2_queue(&s->common, b); 8400e43e99cSbellard ps2_queue(&s->common, dx1 & 0xff); 8410e43e99cSbellard ps2_queue(&s->common, dy1 & 0xff); 8420e43e99cSbellard /* extra byte for IMPS/2 or IMEX */ 8430e43e99cSbellard switch(s->mouse_type) { 8440e43e99cSbellard default: 8450e43e99cSbellard break; 8460e43e99cSbellard case 3: 8470e43e99cSbellard if (dz1 > 127) 8480e43e99cSbellard dz1 = 127; 8490e43e99cSbellard else if (dz1 < -127) 8500e43e99cSbellard dz1 = -127; 8510e43e99cSbellard ps2_queue(&s->common, dz1 & 0xff); 8520e43e99cSbellard break; 8530e43e99cSbellard case 4: 8540e43e99cSbellard if (dz1 > 7) 8550e43e99cSbellard dz1 = 7; 8560e43e99cSbellard else if (dz1 < -7) 8570e43e99cSbellard dz1 = -7; 8580e43e99cSbellard b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); 8590e43e99cSbellard ps2_queue(&s->common, b); 8600e43e99cSbellard break; 8610e43e99cSbellard } 8620e43e99cSbellard 8635edab03dSDon Koch trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b); 8640e43e99cSbellard /* update deltas */ 8650e43e99cSbellard s->mouse_dx -= dx1; 8660e43e99cSbellard s->mouse_dy -= dy1; 8670e43e99cSbellard s->mouse_dz -= dz1; 8680e43e99cSbellard } 8690e43e99cSbellard 8702a766d29SGerd Hoffmann static void ps2_mouse_event(DeviceState *dev, QemuConsole *src, 8712a766d29SGerd Hoffmann InputEvent *evt) 8720e43e99cSbellard { 8737fb1cf16SEric Blake static const int bmap[INPUT_BUTTON__MAX] = { 8742a766d29SGerd Hoffmann [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON, 8752a766d29SGerd Hoffmann [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON, 8762a766d29SGerd Hoffmann [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON, 8772a766d29SGerd Hoffmann }; 8782a766d29SGerd Hoffmann PS2MouseState *s = (PS2MouseState *)dev; 879b5a1b443SEric Blake InputMoveEvent *move; 880b5a1b443SEric Blake InputBtnEvent *btn; 8810e43e99cSbellard 8820e43e99cSbellard /* check if deltas are recorded when disabled */ 8830e43e99cSbellard if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) 8840e43e99cSbellard return; 8850e43e99cSbellard 886568c73a4SEric Blake switch (evt->type) { 8872a766d29SGerd Hoffmann case INPUT_EVENT_KIND_REL: 88832bafa8fSEric Blake move = evt->u.rel.data; 889b5a1b443SEric Blake if (move->axis == INPUT_AXIS_X) { 890b5a1b443SEric Blake s->mouse_dx += move->value; 891b5a1b443SEric Blake } else if (move->axis == INPUT_AXIS_Y) { 892b5a1b443SEric Blake s->mouse_dy -= move->value; 8932a766d29SGerd Hoffmann } 8942a766d29SGerd Hoffmann break; 8950e43e99cSbellard 8962a766d29SGerd Hoffmann case INPUT_EVENT_KIND_BTN: 89732bafa8fSEric Blake btn = evt->u.btn.data; 898b5a1b443SEric Blake if (btn->down) { 899b5a1b443SEric Blake s->mouse_buttons |= bmap[btn->button]; 900b5a1b443SEric Blake if (btn->button == INPUT_BUTTON_WHEEL_UP) { 9012a766d29SGerd Hoffmann s->mouse_dz--; 902b5a1b443SEric Blake } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) { 9032a766d29SGerd Hoffmann s->mouse_dz++; 9042a766d29SGerd Hoffmann } 9052a766d29SGerd Hoffmann } else { 906b5a1b443SEric Blake s->mouse_buttons &= ~bmap[btn->button]; 9072a766d29SGerd Hoffmann } 9082a766d29SGerd Hoffmann break; 9092a766d29SGerd Hoffmann 9102a766d29SGerd Hoffmann default: 9112a766d29SGerd Hoffmann /* keep gcc happy */ 9122a766d29SGerd Hoffmann break; 9132a766d29SGerd Hoffmann } 914fd214d18SGerd Hoffmann } 915fd214d18SGerd Hoffmann 9162a766d29SGerd Hoffmann static void ps2_mouse_sync(DeviceState *dev) 9172a766d29SGerd Hoffmann { 9182a766d29SGerd Hoffmann PS2MouseState *s = (PS2MouseState *)dev; 9192a766d29SGerd Hoffmann 9202a766d29SGerd Hoffmann if (s->mouse_buttons) { 9212a766d29SGerd Hoffmann qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); 9222a766d29SGerd Hoffmann } 9232858ab09SGonglei if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) { 9242858ab09SGonglei while (s->common.queue.count < PS2_QUEUE_SIZE - 4) { 9250e43e99cSbellard /* if not remote, send event. Multiple events are sent if 9260e43e99cSbellard too big deltas */ 9270e43e99cSbellard ps2_mouse_send_packet(s); 9280e43e99cSbellard if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) 9290e43e99cSbellard break; 9300e43e99cSbellard } 9310e43e99cSbellard } 9320e43e99cSbellard } 9330e43e99cSbellard 934548df2acSths void ps2_mouse_fake_event(void *opaque) 935548df2acSths { 9362a766d29SGerd Hoffmann PS2MouseState *s = opaque; 9375edab03dSDon Koch trace_ps2_mouse_fake_event(opaque); 9382a766d29SGerd Hoffmann s->mouse_dx++; 9392a766d29SGerd Hoffmann ps2_mouse_sync(opaque); 940548df2acSths } 941548df2acSths 9420e43e99cSbellard void ps2_write_mouse(void *opaque, int val) 9430e43e99cSbellard { 9440e43e99cSbellard PS2MouseState *s = (PS2MouseState *)opaque; 9455edab03dSDon Koch 9465edab03dSDon Koch trace_ps2_write_mouse(opaque, val); 9470e43e99cSbellard #ifdef DEBUG_MOUSE 9480e43e99cSbellard printf("kbd: write mouse 0x%02x\n", val); 9490e43e99cSbellard #endif 9500e43e99cSbellard switch(s->common.write_cmd) { 9510e43e99cSbellard default: 9520e43e99cSbellard case -1: 9530e43e99cSbellard /* mouse command */ 9540e43e99cSbellard if (s->mouse_wrap) { 9550e43e99cSbellard if (val == AUX_RESET_WRAP) { 9560e43e99cSbellard s->mouse_wrap = 0; 9570e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 9580e43e99cSbellard return; 9590e43e99cSbellard } else if (val != AUX_RESET) { 9600e43e99cSbellard ps2_queue(&s->common, val); 9610e43e99cSbellard return; 9620e43e99cSbellard } 9630e43e99cSbellard } 9640e43e99cSbellard switch(val) { 9650e43e99cSbellard case AUX_SET_SCALE11: 9660e43e99cSbellard s->mouse_status &= ~MOUSE_STATUS_SCALE21; 9670e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 9680e43e99cSbellard break; 9690e43e99cSbellard case AUX_SET_SCALE21: 9700e43e99cSbellard s->mouse_status |= MOUSE_STATUS_SCALE21; 9710e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 9720e43e99cSbellard break; 9730e43e99cSbellard case AUX_SET_STREAM: 9740e43e99cSbellard s->mouse_status &= ~MOUSE_STATUS_REMOTE; 9750e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 9760e43e99cSbellard break; 9770e43e99cSbellard case AUX_SET_WRAP: 9780e43e99cSbellard s->mouse_wrap = 1; 9790e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 9800e43e99cSbellard break; 9810e43e99cSbellard case AUX_SET_REMOTE: 9820e43e99cSbellard s->mouse_status |= MOUSE_STATUS_REMOTE; 9830e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 9840e43e99cSbellard break; 9850e43e99cSbellard case AUX_GET_TYPE: 9860e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 9870e43e99cSbellard ps2_queue(&s->common, s->mouse_type); 9880e43e99cSbellard break; 9890e43e99cSbellard case AUX_SET_RES: 9900e43e99cSbellard case AUX_SET_SAMPLE: 9910e43e99cSbellard s->common.write_cmd = val; 9920e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 9930e43e99cSbellard break; 9940e43e99cSbellard case AUX_GET_SCALE: 9950e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 9960e43e99cSbellard ps2_queue(&s->common, s->mouse_status); 9970e43e99cSbellard ps2_queue(&s->common, s->mouse_resolution); 9980e43e99cSbellard ps2_queue(&s->common, s->mouse_sample_rate); 9990e43e99cSbellard break; 10000e43e99cSbellard case AUX_POLL: 10010e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 10020e43e99cSbellard ps2_mouse_send_packet(s); 10030e43e99cSbellard break; 10040e43e99cSbellard case AUX_ENABLE_DEV: 10050e43e99cSbellard s->mouse_status |= MOUSE_STATUS_ENABLED; 10060e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 10070e43e99cSbellard break; 10080e43e99cSbellard case AUX_DISABLE_DEV: 10090e43e99cSbellard s->mouse_status &= ~MOUSE_STATUS_ENABLED; 10100e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 10110e43e99cSbellard break; 10120e43e99cSbellard case AUX_SET_DEFAULT: 10130e43e99cSbellard s->mouse_sample_rate = 100; 10140e43e99cSbellard s->mouse_resolution = 2; 10150e43e99cSbellard s->mouse_status = 0; 10160e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 10170e43e99cSbellard break; 10180e43e99cSbellard case AUX_RESET: 10190e43e99cSbellard s->mouse_sample_rate = 100; 10200e43e99cSbellard s->mouse_resolution = 2; 10210e43e99cSbellard s->mouse_status = 0; 10220e43e99cSbellard s->mouse_type = 0; 10230e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 10240e43e99cSbellard ps2_queue(&s->common, 0xaa); 10250e43e99cSbellard ps2_queue(&s->common, s->mouse_type); 10260e43e99cSbellard break; 10270e43e99cSbellard default: 10280e43e99cSbellard break; 10290e43e99cSbellard } 10300e43e99cSbellard break; 10310e43e99cSbellard case AUX_SET_SAMPLE: 10320e43e99cSbellard s->mouse_sample_rate = val; 10330e43e99cSbellard /* detect IMPS/2 or IMEX */ 10340e43e99cSbellard switch(s->mouse_detect_state) { 10350e43e99cSbellard default: 10360e43e99cSbellard case 0: 10370e43e99cSbellard if (val == 200) 10380e43e99cSbellard s->mouse_detect_state = 1; 10390e43e99cSbellard break; 10400e43e99cSbellard case 1: 10410e43e99cSbellard if (val == 100) 10420e43e99cSbellard s->mouse_detect_state = 2; 10430e43e99cSbellard else if (val == 200) 10440e43e99cSbellard s->mouse_detect_state = 3; 10450e43e99cSbellard else 10460e43e99cSbellard s->mouse_detect_state = 0; 10470e43e99cSbellard break; 10480e43e99cSbellard case 2: 10490e43e99cSbellard if (val == 80) 10500e43e99cSbellard s->mouse_type = 3; /* IMPS/2 */ 10510e43e99cSbellard s->mouse_detect_state = 0; 10520e43e99cSbellard break; 10530e43e99cSbellard case 3: 10540e43e99cSbellard if (val == 80) 10550e43e99cSbellard s->mouse_type = 4; /* IMEX */ 10560e43e99cSbellard s->mouse_detect_state = 0; 10570e43e99cSbellard break; 10580e43e99cSbellard } 10590e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 10600e43e99cSbellard s->common.write_cmd = -1; 10610e43e99cSbellard break; 10620e43e99cSbellard case AUX_SET_RES: 10630e43e99cSbellard s->mouse_resolution = val; 10640e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 10650e43e99cSbellard s->common.write_cmd = -1; 10660e43e99cSbellard break; 10670e43e99cSbellard } 10680e43e99cSbellard } 10690e43e99cSbellard 1070ef74679aSDinesh Subhraveti static void ps2_common_reset(PS2State *s) 10710e43e99cSbellard { 10720e43e99cSbellard PS2Queue *q; 10730e43e99cSbellard s->write_cmd = -1; 10740e43e99cSbellard q = &s->queue; 10750e43e99cSbellard q->rptr = 0; 10760e43e99cSbellard q->wptr = 0; 10770e43e99cSbellard q->count = 0; 1078deeccef3Saliguori s->update_irq(s->update_arg, 0); 10790e43e99cSbellard } 10800e43e99cSbellard 10812858ab09SGonglei static void ps2_common_post_load(PS2State *s) 10822858ab09SGonglei { 10832858ab09SGonglei PS2Queue *q = &s->queue; 10842858ab09SGonglei int size; 10852858ab09SGonglei int i; 10862858ab09SGonglei int tmp_data[PS2_QUEUE_SIZE]; 10872858ab09SGonglei 10882858ab09SGonglei /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */ 10892858ab09SGonglei size = q->count > PS2_QUEUE_SIZE ? 0 : q->count; 10902858ab09SGonglei 10912858ab09SGonglei /* move the queue elements to the start of data array */ 10922858ab09SGonglei if (size > 0) { 10932858ab09SGonglei for (i = 0; i < size; i++) { 10942858ab09SGonglei /* move the queue elements to the temporary buffer */ 10952858ab09SGonglei tmp_data[i] = q->data[q->rptr]; 10962858ab09SGonglei if (++q->rptr == 256) { 10972858ab09SGonglei q->rptr = 0; 10982858ab09SGonglei } 10992858ab09SGonglei } 11002858ab09SGonglei memcpy(q->data, tmp_data, size); 11012858ab09SGonglei } 11022858ab09SGonglei /* reset rptr/wptr/count */ 11032858ab09SGonglei q->rptr = 0; 11042858ab09SGonglei q->wptr = size; 11052858ab09SGonglei q->count = size; 11062858ab09SGonglei s->update_irq(s->update_arg, q->count != 0); 11072858ab09SGonglei } 11082858ab09SGonglei 1109ef74679aSDinesh Subhraveti static void ps2_kbd_reset(void *opaque) 1110ef74679aSDinesh Subhraveti { 1111ef74679aSDinesh Subhraveti PS2KbdState *s = (PS2KbdState *) opaque; 1112ef74679aSDinesh Subhraveti 11135edab03dSDon Koch trace_ps2_kbd_reset(opaque); 1114ef74679aSDinesh Subhraveti ps2_common_reset(&s->common); 1115ef74679aSDinesh Subhraveti s->scan_enabled = 0; 1116ef74679aSDinesh Subhraveti s->translate = 0; 1117089adafdSHervé Poussineau s->scancode_set = 2; 1118ef74679aSDinesh Subhraveti } 1119ef74679aSDinesh Subhraveti 1120ef74679aSDinesh Subhraveti static void ps2_mouse_reset(void *opaque) 1121ef74679aSDinesh Subhraveti { 1122ef74679aSDinesh Subhraveti PS2MouseState *s = (PS2MouseState *) opaque; 1123ef74679aSDinesh Subhraveti 11245edab03dSDon Koch trace_ps2_mouse_reset(opaque); 1125ef74679aSDinesh Subhraveti ps2_common_reset(&s->common); 1126ef74679aSDinesh Subhraveti s->mouse_status = 0; 1127ef74679aSDinesh Subhraveti s->mouse_resolution = 0; 1128ef74679aSDinesh Subhraveti s->mouse_sample_rate = 0; 1129ef74679aSDinesh Subhraveti s->mouse_wrap = 0; 1130ef74679aSDinesh Subhraveti s->mouse_type = 0; 1131ef74679aSDinesh Subhraveti s->mouse_detect_state = 0; 1132ef74679aSDinesh Subhraveti s->mouse_dx = 0; 1133ef74679aSDinesh Subhraveti s->mouse_dy = 0; 1134ef74679aSDinesh Subhraveti s->mouse_dz = 0; 1135ef74679aSDinesh Subhraveti s->mouse_buttons = 0; 1136ef74679aSDinesh Subhraveti } 1137ef74679aSDinesh Subhraveti 1138b31442c3SJuan Quintela static const VMStateDescription vmstate_ps2_common = { 1139b31442c3SJuan Quintela .name = "PS2 Common State", 1140b31442c3SJuan Quintela .version_id = 3, 1141b31442c3SJuan Quintela .minimum_version_id = 2, 1142b31442c3SJuan Quintela .fields = (VMStateField[]) { 1143b31442c3SJuan Quintela VMSTATE_INT32(write_cmd, PS2State), 1144b31442c3SJuan Quintela VMSTATE_INT32(queue.rptr, PS2State), 1145b31442c3SJuan Quintela VMSTATE_INT32(queue.wptr, PS2State), 1146b31442c3SJuan Quintela VMSTATE_INT32(queue.count, PS2State), 1147b31442c3SJuan Quintela VMSTATE_BUFFER(queue.data, PS2State), 1148b31442c3SJuan Quintela VMSTATE_END_OF_LIST() 11497783e9f0Spbrook } 1150b31442c3SJuan Quintela }; 11517783e9f0Spbrook 11527f540ab5SChristophe Fergeau static bool ps2_keyboard_ledstate_needed(void *opaque) 11537f540ab5SChristophe Fergeau { 11547f540ab5SChristophe Fergeau PS2KbdState *s = opaque; 11557f540ab5SChristophe Fergeau 11567f540ab5SChristophe Fergeau return s->ledstate != 0; /* 0 is default state */ 11577f540ab5SChristophe Fergeau } 11587f540ab5SChristophe Fergeau 11597f540ab5SChristophe Fergeau static int ps2_kbd_ledstate_post_load(void *opaque, int version_id) 11607f540ab5SChristophe Fergeau { 11617f540ab5SChristophe Fergeau PS2KbdState *s = opaque; 11627f540ab5SChristophe Fergeau 11637f540ab5SChristophe Fergeau kbd_put_ledstate(s->ledstate); 11647f540ab5SChristophe Fergeau return 0; 11657f540ab5SChristophe Fergeau } 11667f540ab5SChristophe Fergeau 11677f540ab5SChristophe Fergeau static const VMStateDescription vmstate_ps2_keyboard_ledstate = { 11687f540ab5SChristophe Fergeau .name = "ps2kbd/ledstate", 11697f540ab5SChristophe Fergeau .version_id = 3, 11707f540ab5SChristophe Fergeau .minimum_version_id = 2, 11717f540ab5SChristophe Fergeau .post_load = ps2_kbd_ledstate_post_load, 11725cd8cadaSJuan Quintela .needed = ps2_keyboard_ledstate_needed, 11737f540ab5SChristophe Fergeau .fields = (VMStateField[]) { 11747f540ab5SChristophe Fergeau VMSTATE_INT32(ledstate, PS2KbdState), 11757f540ab5SChristophe Fergeau VMSTATE_END_OF_LIST() 11767f540ab5SChristophe Fergeau } 11777f540ab5SChristophe Fergeau }; 11787f540ab5SChristophe Fergeau 117957d5c005SHervé Poussineau static bool ps2_keyboard_need_high_bit_needed(void *opaque) 118057d5c005SHervé Poussineau { 118157d5c005SHervé Poussineau PS2KbdState *s = opaque; 118257d5c005SHervé Poussineau return s->need_high_bit != 0; /* 0 is the usual state */ 118357d5c005SHervé Poussineau } 118457d5c005SHervé Poussineau 118557d5c005SHervé Poussineau static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = { 118657d5c005SHervé Poussineau .name = "ps2kbd/need_high_bit", 118757d5c005SHervé Poussineau .version_id = 1, 118857d5c005SHervé Poussineau .minimum_version_id = 1, 118957d5c005SHervé Poussineau .needed = ps2_keyboard_need_high_bit_needed, 119057d5c005SHervé Poussineau .fields = (VMStateField[]) { 119157d5c005SHervé Poussineau VMSTATE_BOOL(need_high_bit, PS2KbdState), 119257d5c005SHervé Poussineau VMSTATE_END_OF_LIST() 119357d5c005SHervé Poussineau } 119457d5c005SHervé Poussineau }; 119557d5c005SHervé Poussineau 1196db596c53SJuan Quintela static int ps2_kbd_post_load(void* opaque, int version_id) 11970e43e99cSbellard { 11980e43e99cSbellard PS2KbdState *s = (PS2KbdState*)opaque; 11992858ab09SGonglei PS2State *ps2 = &s->common; 12000e43e99cSbellard 1201db596c53SJuan Quintela if (version_id == 2) 1202e7d93956Saurel32 s->scancode_set=2; 12032858ab09SGonglei 12042858ab09SGonglei ps2_common_post_load(ps2); 12052858ab09SGonglei 12060e43e99cSbellard return 0; 12070e43e99cSbellard } 12080e43e99cSbellard 12092858ab09SGonglei static void ps2_kbd_pre_save(void *opaque) 12102858ab09SGonglei { 12112858ab09SGonglei PS2KbdState *s = (PS2KbdState *)opaque; 12122858ab09SGonglei PS2State *ps2 = &s->common; 12132858ab09SGonglei 12142858ab09SGonglei ps2_common_post_load(ps2); 12152858ab09SGonglei } 12162858ab09SGonglei 1217b31442c3SJuan Quintela static const VMStateDescription vmstate_ps2_keyboard = { 1218b31442c3SJuan Quintela .name = "ps2kbd", 1219b31442c3SJuan Quintela .version_id = 3, 1220db596c53SJuan Quintela .minimum_version_id = 2, 1221db596c53SJuan Quintela .post_load = ps2_kbd_post_load, 12222858ab09SGonglei .pre_save = ps2_kbd_pre_save, 1223b31442c3SJuan Quintela .fields = (VMStateField[]) { 1224b31442c3SJuan Quintela VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State), 1225b31442c3SJuan Quintela VMSTATE_INT32(scan_enabled, PS2KbdState), 1226b31442c3SJuan Quintela VMSTATE_INT32(translate, PS2KbdState), 1227b31442c3SJuan Quintela VMSTATE_INT32_V(scancode_set, PS2KbdState,3), 1228b31442c3SJuan Quintela VMSTATE_END_OF_LIST() 12297f540ab5SChristophe Fergeau }, 12305cd8cadaSJuan Quintela .subsections = (const VMStateDescription*[]) { 12315cd8cadaSJuan Quintela &vmstate_ps2_keyboard_ledstate, 123257d5c005SHervé Poussineau &vmstate_ps2_keyboard_need_high_bit, 12335cd8cadaSJuan Quintela NULL 12340e43e99cSbellard } 1235b31442c3SJuan Quintela }; 1236b31442c3SJuan Quintela 12372858ab09SGonglei static int ps2_mouse_post_load(void *opaque, int version_id) 12382858ab09SGonglei { 12392858ab09SGonglei PS2MouseState *s = (PS2MouseState *)opaque; 12402858ab09SGonglei PS2State *ps2 = &s->common; 12412858ab09SGonglei 12422858ab09SGonglei ps2_common_post_load(ps2); 12432858ab09SGonglei 12442858ab09SGonglei return 0; 12452858ab09SGonglei } 12462858ab09SGonglei 12472858ab09SGonglei static void ps2_mouse_pre_save(void *opaque) 12482858ab09SGonglei { 12492858ab09SGonglei PS2MouseState *s = (PS2MouseState *)opaque; 12502858ab09SGonglei PS2State *ps2 = &s->common; 12512858ab09SGonglei 12522858ab09SGonglei ps2_common_post_load(ps2); 12532858ab09SGonglei } 12542858ab09SGonglei 1255b31442c3SJuan Quintela static const VMStateDescription vmstate_ps2_mouse = { 1256b31442c3SJuan Quintela .name = "ps2mouse", 1257b31442c3SJuan Quintela .version_id = 2, 1258b31442c3SJuan Quintela .minimum_version_id = 2, 12592858ab09SGonglei .post_load = ps2_mouse_post_load, 12602858ab09SGonglei .pre_save = ps2_mouse_pre_save, 1261b31442c3SJuan Quintela .fields = (VMStateField[]) { 1262b31442c3SJuan Quintela VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State), 1263b31442c3SJuan Quintela VMSTATE_UINT8(mouse_status, PS2MouseState), 1264b31442c3SJuan Quintela VMSTATE_UINT8(mouse_resolution, PS2MouseState), 1265b31442c3SJuan Quintela VMSTATE_UINT8(mouse_sample_rate, PS2MouseState), 1266b31442c3SJuan Quintela VMSTATE_UINT8(mouse_wrap, PS2MouseState), 1267b31442c3SJuan Quintela VMSTATE_UINT8(mouse_type, PS2MouseState), 1268b31442c3SJuan Quintela VMSTATE_UINT8(mouse_detect_state, PS2MouseState), 1269b31442c3SJuan Quintela VMSTATE_INT32(mouse_dx, PS2MouseState), 1270b31442c3SJuan Quintela VMSTATE_INT32(mouse_dy, PS2MouseState), 1271b31442c3SJuan Quintela VMSTATE_INT32(mouse_dz, PS2MouseState), 1272b31442c3SJuan Quintela VMSTATE_UINT8(mouse_buttons, PS2MouseState), 1273b31442c3SJuan Quintela VMSTATE_END_OF_LIST() 1274b31442c3SJuan Quintela } 1275b31442c3SJuan Quintela }; 12760e43e99cSbellard 127766e6536eSGerd Hoffmann static QemuInputHandler ps2_keyboard_handler = { 127866e6536eSGerd Hoffmann .name = "QEMU PS/2 Keyboard", 127966e6536eSGerd Hoffmann .mask = INPUT_EVENT_MASK_KEY, 128066e6536eSGerd Hoffmann .event = ps2_keyboard_event, 128166e6536eSGerd Hoffmann }; 128266e6536eSGerd Hoffmann 12830e43e99cSbellard void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) 12840e43e99cSbellard { 12857267c094SAnthony Liguori PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState)); 12860e43e99cSbellard 12875edab03dSDon Koch trace_ps2_kbd_init(s); 12880e43e99cSbellard s->common.update_irq = update_irq; 12890e43e99cSbellard s->common.update_arg = update_arg; 1290e7d93956Saurel32 s->scancode_set = 2; 12910be71e32SAlex Williamson vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s); 129266e6536eSGerd Hoffmann qemu_input_handler_register((DeviceState *)s, 129366e6536eSGerd Hoffmann &ps2_keyboard_handler); 1294ef74679aSDinesh Subhraveti qemu_register_reset(ps2_kbd_reset, s); 12950e43e99cSbellard return s; 12960e43e99cSbellard } 12970e43e99cSbellard 12982a766d29SGerd Hoffmann static QemuInputHandler ps2_mouse_handler = { 12992a766d29SGerd Hoffmann .name = "QEMU PS/2 Mouse", 13002a766d29SGerd Hoffmann .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, 13012a766d29SGerd Hoffmann .event = ps2_mouse_event, 13022a766d29SGerd Hoffmann .sync = ps2_mouse_sync, 13032a766d29SGerd Hoffmann }; 13042a766d29SGerd Hoffmann 13050e43e99cSbellard void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) 13060e43e99cSbellard { 13077267c094SAnthony Liguori PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState)); 13080e43e99cSbellard 13095edab03dSDon Koch trace_ps2_mouse_init(s); 13100e43e99cSbellard s->common.update_irq = update_irq; 13110e43e99cSbellard s->common.update_arg = update_arg; 13120be71e32SAlex Williamson vmstate_register(NULL, 0, &vmstate_ps2_mouse, s); 13132a766d29SGerd Hoffmann qemu_input_handler_register((DeviceState *)s, 13142a766d29SGerd Hoffmann &ps2_mouse_handler); 1315ef74679aSDinesh Subhraveti qemu_register_reset(ps2_mouse_reset, s); 13160e43e99cSbellard return s; 13170e43e99cSbellard } 1318