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" 25ec044a80SHervé 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 81620775d1SDaniel P. Berrange /* Bits for 'modifiers' field in PS2KbdState */ 82620775d1SDaniel P. Berrange #define MOD_CTRL_L (1 << 0) 83620775d1SDaniel P. Berrange #define MOD_SHIFT_L (1 << 1) 84620775d1SDaniel P. Berrange #define MOD_ALT_L (1 << 2) 85620775d1SDaniel P. Berrange #define MOD_CTRL_R (1 << 3) 86620775d1SDaniel P. Berrange #define MOD_SHIFT_R (1 << 4) 87620775d1SDaniel P. Berrange #define MOD_ALT_R (1 << 5) 88620775d1SDaniel P. Berrange 890e43e99cSbellard typedef struct { 902858ab09SGonglei /* Keep the data array 256 bytes long, which compatibility 912858ab09SGonglei with older qemu versions. */ 922858ab09SGonglei uint8_t data[256]; 930e43e99cSbellard int rptr, wptr, count; 940e43e99cSbellard } PS2Queue; 950e43e99cSbellard 968498bb8dSGerd Hoffmann struct PS2State { 970e43e99cSbellard PS2Queue queue; 980e43e99cSbellard int32_t write_cmd; 990e43e99cSbellard void (*update_irq)(void *, int); 1000e43e99cSbellard void *update_arg; 1018498bb8dSGerd Hoffmann }; 1020e43e99cSbellard 1030e43e99cSbellard typedef struct { 1040e43e99cSbellard PS2State common; 1050e43e99cSbellard int scan_enabled; 106f94f5d71Spbrook int translate; 107e7d93956Saurel32 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */ 1087f540ab5SChristophe Fergeau int ledstate; 10957d5c005SHervé Poussineau bool need_high_bit; 110620775d1SDaniel P. Berrange unsigned int modifiers; /* bitmask of MOD_* constants above */ 1110e43e99cSbellard } PS2KbdState; 1120e43e99cSbellard 1130e43e99cSbellard typedef struct { 1140e43e99cSbellard PS2State common; 1150e43e99cSbellard uint8_t mouse_status; 1160e43e99cSbellard uint8_t mouse_resolution; 1170e43e99cSbellard uint8_t mouse_sample_rate; 1180e43e99cSbellard uint8_t mouse_wrap; 1190e43e99cSbellard uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */ 1200e43e99cSbellard uint8_t mouse_detect_state; 1210e43e99cSbellard int mouse_dx; /* current values, needed for 'poll' mode */ 1220e43e99cSbellard int mouse_dy; 1230e43e99cSbellard int mouse_dz; 1240e43e99cSbellard uint8_t mouse_buttons; 1250e43e99cSbellard } PS2MouseState; 1260e43e99cSbellard 1278c10e0baSHervé Poussineau /* Table to convert from QEMU codes to scancodes. */ 1288c10e0baSHervé Poussineau static const uint16_t qcode_to_keycode_set1[Q_KEY_CODE__MAX] = { 1298c10e0baSHervé Poussineau [0 ... Q_KEY_CODE__MAX - 1] = 0, 1308c10e0baSHervé Poussineau 1318c10e0baSHervé Poussineau [Q_KEY_CODE_A] = 0x1e, 1328c10e0baSHervé Poussineau [Q_KEY_CODE_B] = 0x30, 1338c10e0baSHervé Poussineau [Q_KEY_CODE_C] = 0x2e, 1348c10e0baSHervé Poussineau [Q_KEY_CODE_D] = 0x20, 1358c10e0baSHervé Poussineau [Q_KEY_CODE_E] = 0x12, 1368c10e0baSHervé Poussineau [Q_KEY_CODE_F] = 0x21, 1378c10e0baSHervé Poussineau [Q_KEY_CODE_G] = 0x22, 1388c10e0baSHervé Poussineau [Q_KEY_CODE_H] = 0x23, 1398c10e0baSHervé Poussineau [Q_KEY_CODE_I] = 0x17, 1408c10e0baSHervé Poussineau [Q_KEY_CODE_J] = 0x24, 1418c10e0baSHervé Poussineau [Q_KEY_CODE_K] = 0x25, 1428c10e0baSHervé Poussineau [Q_KEY_CODE_L] = 0x26, 1438c10e0baSHervé Poussineau [Q_KEY_CODE_M] = 0x32, 1448c10e0baSHervé Poussineau [Q_KEY_CODE_N] = 0x31, 1458c10e0baSHervé Poussineau [Q_KEY_CODE_O] = 0x18, 1468c10e0baSHervé Poussineau [Q_KEY_CODE_P] = 0x19, 1478c10e0baSHervé Poussineau [Q_KEY_CODE_Q] = 0x10, 1488c10e0baSHervé Poussineau [Q_KEY_CODE_R] = 0x13, 1498c10e0baSHervé Poussineau [Q_KEY_CODE_S] = 0x1f, 1508c10e0baSHervé Poussineau [Q_KEY_CODE_T] = 0x14, 1518c10e0baSHervé Poussineau [Q_KEY_CODE_U] = 0x16, 1528c10e0baSHervé Poussineau [Q_KEY_CODE_V] = 0x2f, 1538c10e0baSHervé Poussineau [Q_KEY_CODE_W] = 0x11, 1548c10e0baSHervé Poussineau [Q_KEY_CODE_X] = 0x2d, 1558c10e0baSHervé Poussineau [Q_KEY_CODE_Y] = 0x15, 1568c10e0baSHervé Poussineau [Q_KEY_CODE_Z] = 0x2c, 1578c10e0baSHervé Poussineau [Q_KEY_CODE_0] = 0x0b, 1588c10e0baSHervé Poussineau [Q_KEY_CODE_1] = 0x02, 1598c10e0baSHervé Poussineau [Q_KEY_CODE_2] = 0x03, 1608c10e0baSHervé Poussineau [Q_KEY_CODE_3] = 0x04, 1618c10e0baSHervé Poussineau [Q_KEY_CODE_4] = 0x05, 1628c10e0baSHervé Poussineau [Q_KEY_CODE_5] = 0x06, 1638c10e0baSHervé Poussineau [Q_KEY_CODE_6] = 0x07, 1648c10e0baSHervé Poussineau [Q_KEY_CODE_7] = 0x08, 1658c10e0baSHervé Poussineau [Q_KEY_CODE_8] = 0x09, 1668c10e0baSHervé Poussineau [Q_KEY_CODE_9] = 0x0a, 1678c10e0baSHervé Poussineau [Q_KEY_CODE_GRAVE_ACCENT] = 0x29, 1688c10e0baSHervé Poussineau [Q_KEY_CODE_MINUS] = 0x0c, 1698c10e0baSHervé Poussineau [Q_KEY_CODE_EQUAL] = 0x0d, 1708c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSLASH] = 0x2b, 1718c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSPACE] = 0x0e, 1728c10e0baSHervé Poussineau [Q_KEY_CODE_SPC] = 0x39, 1738c10e0baSHervé Poussineau [Q_KEY_CODE_TAB] = 0x0f, 1748c10e0baSHervé Poussineau [Q_KEY_CODE_CAPS_LOCK] = 0x3a, 1758c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT] = 0x2a, 1768c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL] = 0x1d, 1778c10e0baSHervé Poussineau [Q_KEY_CODE_META_L] = 0xe05b, 1788c10e0baSHervé Poussineau [Q_KEY_CODE_ALT] = 0x38, 1798c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT_R] = 0x36, 1808c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL_R] = 0xe01d, 1818c10e0baSHervé Poussineau [Q_KEY_CODE_META_R] = 0xe05c, 1828c10e0baSHervé Poussineau [Q_KEY_CODE_ALT_R] = 0xe038, 1838c10e0baSHervé Poussineau [Q_KEY_CODE_MENU] = 0xe05d, 1848c10e0baSHervé Poussineau [Q_KEY_CODE_RET] = 0x1c, 1858c10e0baSHervé Poussineau [Q_KEY_CODE_ESC] = 0x01, 1868c10e0baSHervé Poussineau [Q_KEY_CODE_F1] = 0x3b, 1878c10e0baSHervé Poussineau [Q_KEY_CODE_F2] = 0x3c, 1888c10e0baSHervé Poussineau [Q_KEY_CODE_F3] = 0x3d, 1898c10e0baSHervé Poussineau [Q_KEY_CODE_F4] = 0x3e, 1908c10e0baSHervé Poussineau [Q_KEY_CODE_F5] = 0x3f, 1918c10e0baSHervé Poussineau [Q_KEY_CODE_F6] = 0x40, 1928c10e0baSHervé Poussineau [Q_KEY_CODE_F7] = 0x41, 1938c10e0baSHervé Poussineau [Q_KEY_CODE_F8] = 0x42, 1948c10e0baSHervé Poussineau [Q_KEY_CODE_F9] = 0x43, 1958c10e0baSHervé Poussineau [Q_KEY_CODE_F10] = 0x44, 1968c10e0baSHervé Poussineau [Q_KEY_CODE_F11] = 0x57, 1978c10e0baSHervé Poussineau [Q_KEY_CODE_F12] = 0x58, 1988c10e0baSHervé Poussineau /* special handling for Q_KEY_CODE_PRINT */ 1998c10e0baSHervé Poussineau [Q_KEY_CODE_SCROLL_LOCK] = 0x46, 2008c10e0baSHervé Poussineau /* special handling for Q_KEY_CODE_PAUSE */ 2018c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_LEFT] = 0x1a, 2028c10e0baSHervé Poussineau [Q_KEY_CODE_INSERT] = 0xe052, 2038c10e0baSHervé Poussineau [Q_KEY_CODE_HOME] = 0xe047, 2048c10e0baSHervé Poussineau [Q_KEY_CODE_PGUP] = 0xe049, 2058c10e0baSHervé Poussineau [Q_KEY_CODE_DELETE] = 0xe053, 2068c10e0baSHervé Poussineau [Q_KEY_CODE_END] = 0xe04f, 2078c10e0baSHervé Poussineau [Q_KEY_CODE_PGDN] = 0xe051, 2088c10e0baSHervé Poussineau [Q_KEY_CODE_UP] = 0xe048, 2098c10e0baSHervé Poussineau [Q_KEY_CODE_LEFT] = 0xe04b, 2108c10e0baSHervé Poussineau [Q_KEY_CODE_DOWN] = 0xe050, 2118c10e0baSHervé Poussineau [Q_KEY_CODE_RIGHT] = 0xe04d, 2128c10e0baSHervé Poussineau [Q_KEY_CODE_NUM_LOCK] = 0x45, 2138c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DIVIDE] = 0xe035, 2148c10e0baSHervé Poussineau [Q_KEY_CODE_KP_MULTIPLY] = 0x37, 2158c10e0baSHervé Poussineau [Q_KEY_CODE_KP_SUBTRACT] = 0x4a, 2168c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ADD] = 0x4e, 2178c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ENTER] = 0xe01c, 2188c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DECIMAL] = 0x53, 2198c10e0baSHervé Poussineau [Q_KEY_CODE_KP_0] = 0x52, 2208c10e0baSHervé Poussineau [Q_KEY_CODE_KP_1] = 0x4f, 2218c10e0baSHervé Poussineau [Q_KEY_CODE_KP_2] = 0x50, 2228c10e0baSHervé Poussineau [Q_KEY_CODE_KP_3] = 0x51, 2238c10e0baSHervé Poussineau [Q_KEY_CODE_KP_4] = 0x4b, 2248c10e0baSHervé Poussineau [Q_KEY_CODE_KP_5] = 0x4c, 2258c10e0baSHervé Poussineau [Q_KEY_CODE_KP_6] = 0x4d, 2268c10e0baSHervé Poussineau [Q_KEY_CODE_KP_7] = 0x47, 2278c10e0baSHervé Poussineau [Q_KEY_CODE_KP_8] = 0x48, 2288c10e0baSHervé Poussineau [Q_KEY_CODE_KP_9] = 0x49, 2298c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b, 2308c10e0baSHervé Poussineau [Q_KEY_CODE_SEMICOLON] = 0x27, 2318c10e0baSHervé Poussineau [Q_KEY_CODE_APOSTROPHE] = 0x28, 2328c10e0baSHervé Poussineau [Q_KEY_CODE_COMMA] = 0x33, 2338c10e0baSHervé Poussineau [Q_KEY_CODE_DOT] = 0x34, 2348c10e0baSHervé Poussineau [Q_KEY_CODE_SLASH] = 0x35, 2358c10e0baSHervé Poussineau 2368c10e0baSHervé Poussineau [Q_KEY_CODE_POWER] = 0x0e5e, 2378c10e0baSHervé Poussineau [Q_KEY_CODE_SLEEP] = 0x0e5f, 2388c10e0baSHervé Poussineau [Q_KEY_CODE_WAKE] = 0x0e63, 2398c10e0baSHervé Poussineau 2408c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIONEXT] = 0xe019, 2418c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOPREV] = 0xe010, 2428c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOSTOP] = 0xe024, 2438c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOPLAY] = 0xe022, 2448c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOMUTE] = 0xe020, 2458c10e0baSHervé Poussineau [Q_KEY_CODE_VOLUMEUP] = 0xe030, 2468c10e0baSHervé Poussineau [Q_KEY_CODE_VOLUMEDOWN] = 0xe02e, 2478c10e0baSHervé Poussineau [Q_KEY_CODE_MEDIASELECT] = 0xe06d, 2488c10e0baSHervé Poussineau [Q_KEY_CODE_MAIL] = 0xe06c, 2498c10e0baSHervé Poussineau [Q_KEY_CODE_CALCULATOR] = 0xe021, 2508c10e0baSHervé Poussineau [Q_KEY_CODE_COMPUTER] = 0xe06b, 251103dce8fSGerd Hoffmann [Q_KEY_CODE_FIND] = 0xe065, 2528c10e0baSHervé Poussineau [Q_KEY_CODE_AC_HOME] = 0xe032, 2538c10e0baSHervé Poussineau [Q_KEY_CODE_AC_BACK] = 0xe06a, 2548c10e0baSHervé Poussineau [Q_KEY_CODE_AC_FORWARD] = 0xe069, 255103dce8fSGerd Hoffmann [Q_KEY_CODE_STOP] = 0xe068, 2568c10e0baSHervé Poussineau [Q_KEY_CODE_AC_REFRESH] = 0xe067, 2578c10e0baSHervé Poussineau [Q_KEY_CODE_AC_BOOKMARKS] = 0xe066, 2588c10e0baSHervé Poussineau 2598c10e0baSHervé Poussineau [Q_KEY_CODE_ASTERISK] = 0x37, 2608c10e0baSHervé Poussineau [Q_KEY_CODE_LESS] = 0x56, 2618c10e0baSHervé Poussineau [Q_KEY_CODE_RO] = 0x73, 262e9346441SOGAWA Hirofumi [Q_KEY_CODE_HIRAGANA] = 0x70, 263e9346441SOGAWA Hirofumi [Q_KEY_CODE_HENKAN] = 0x79, 264e9346441SOGAWA Hirofumi [Q_KEY_CODE_YEN] = 0x7d, 2658c10e0baSHervé Poussineau [Q_KEY_CODE_KP_COMMA] = 0x7e, 266f94f5d71Spbrook }; 2678c10e0baSHervé Poussineau 2688c10e0baSHervé Poussineau static const uint16_t qcode_to_keycode_set2[Q_KEY_CODE__MAX] = { 2698c10e0baSHervé Poussineau [0 ... Q_KEY_CODE__MAX - 1] = 0, 2708c10e0baSHervé Poussineau 2718c10e0baSHervé Poussineau [Q_KEY_CODE_A] = 0x1c, 2728c10e0baSHervé Poussineau [Q_KEY_CODE_B] = 0x32, 2738c10e0baSHervé Poussineau [Q_KEY_CODE_C] = 0x21, 2748c10e0baSHervé Poussineau [Q_KEY_CODE_D] = 0x23, 2758c10e0baSHervé Poussineau [Q_KEY_CODE_E] = 0x24, 2768c10e0baSHervé Poussineau [Q_KEY_CODE_F] = 0x2b, 2778c10e0baSHervé Poussineau [Q_KEY_CODE_G] = 0x34, 2788c10e0baSHervé Poussineau [Q_KEY_CODE_H] = 0x33, 2798c10e0baSHervé Poussineau [Q_KEY_CODE_I] = 0x43, 2808c10e0baSHervé Poussineau [Q_KEY_CODE_J] = 0x3b, 2818c10e0baSHervé Poussineau [Q_KEY_CODE_K] = 0x42, 2828c10e0baSHervé Poussineau [Q_KEY_CODE_L] = 0x4b, 2838c10e0baSHervé Poussineau [Q_KEY_CODE_M] = 0x3a, 2848c10e0baSHervé Poussineau [Q_KEY_CODE_N] = 0x31, 2858c10e0baSHervé Poussineau [Q_KEY_CODE_O] = 0x44, 2868c10e0baSHervé Poussineau [Q_KEY_CODE_P] = 0x4d, 2878c10e0baSHervé Poussineau [Q_KEY_CODE_Q] = 0x15, 2888c10e0baSHervé Poussineau [Q_KEY_CODE_R] = 0x2d, 2898c10e0baSHervé Poussineau [Q_KEY_CODE_S] = 0x1b, 2908c10e0baSHervé Poussineau [Q_KEY_CODE_T] = 0x2c, 2918c10e0baSHervé Poussineau [Q_KEY_CODE_U] = 0x3c, 2928c10e0baSHervé Poussineau [Q_KEY_CODE_V] = 0x2a, 2938c10e0baSHervé Poussineau [Q_KEY_CODE_W] = 0x1d, 2948c10e0baSHervé Poussineau [Q_KEY_CODE_X] = 0x22, 2958c10e0baSHervé Poussineau [Q_KEY_CODE_Y] = 0x35, 2968c10e0baSHervé Poussineau [Q_KEY_CODE_Z] = 0x1a, 2978c10e0baSHervé Poussineau [Q_KEY_CODE_0] = 0x45, 2988c10e0baSHervé Poussineau [Q_KEY_CODE_1] = 0x16, 2998c10e0baSHervé Poussineau [Q_KEY_CODE_2] = 0x1e, 3008c10e0baSHervé Poussineau [Q_KEY_CODE_3] = 0x26, 3018c10e0baSHervé Poussineau [Q_KEY_CODE_4] = 0x25, 3028c10e0baSHervé Poussineau [Q_KEY_CODE_5] = 0x2e, 3038c10e0baSHervé Poussineau [Q_KEY_CODE_6] = 0x36, 3048c10e0baSHervé Poussineau [Q_KEY_CODE_7] = 0x3d, 3058c10e0baSHervé Poussineau [Q_KEY_CODE_8] = 0x3e, 3068c10e0baSHervé Poussineau [Q_KEY_CODE_9] = 0x46, 3078c10e0baSHervé Poussineau [Q_KEY_CODE_GRAVE_ACCENT] = 0x0e, 3088c10e0baSHervé Poussineau [Q_KEY_CODE_MINUS] = 0x4e, 3098c10e0baSHervé Poussineau [Q_KEY_CODE_EQUAL] = 0x55, 3108c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSLASH] = 0x5d, 3118c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSPACE] = 0x66, 3128c10e0baSHervé Poussineau [Q_KEY_CODE_SPC] = 0x29, 3138c10e0baSHervé Poussineau [Q_KEY_CODE_TAB] = 0x0d, 3148c10e0baSHervé Poussineau [Q_KEY_CODE_CAPS_LOCK] = 0x58, 3158c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT] = 0x12, 3168c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL] = 0x14, 3178c10e0baSHervé Poussineau [Q_KEY_CODE_META_L] = 0xe01f, 3188c10e0baSHervé Poussineau [Q_KEY_CODE_ALT] = 0x11, 3198c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT_R] = 0x59, 3208c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL_R] = 0xe014, 3218c10e0baSHervé Poussineau [Q_KEY_CODE_META_R] = 0xe027, 3228c10e0baSHervé Poussineau [Q_KEY_CODE_ALT_R] = 0xe011, 3238c10e0baSHervé Poussineau [Q_KEY_CODE_MENU] = 0xe02f, 3248c10e0baSHervé Poussineau [Q_KEY_CODE_RET] = 0x5a, 3258c10e0baSHervé Poussineau [Q_KEY_CODE_ESC] = 0x76, 3268c10e0baSHervé Poussineau [Q_KEY_CODE_F1] = 0x05, 3278c10e0baSHervé Poussineau [Q_KEY_CODE_F2] = 0x06, 3288c10e0baSHervé Poussineau [Q_KEY_CODE_F3] = 0x04, 3298c10e0baSHervé Poussineau [Q_KEY_CODE_F4] = 0x0c, 3308c10e0baSHervé Poussineau [Q_KEY_CODE_F5] = 0x03, 3318c10e0baSHervé Poussineau [Q_KEY_CODE_F6] = 0x0b, 3328c10e0baSHervé Poussineau [Q_KEY_CODE_F7] = 0x83, 3338c10e0baSHervé Poussineau [Q_KEY_CODE_F8] = 0x0a, 3348c10e0baSHervé Poussineau [Q_KEY_CODE_F9] = 0x01, 3358c10e0baSHervé Poussineau [Q_KEY_CODE_F10] = 0x09, 3368c10e0baSHervé Poussineau [Q_KEY_CODE_F11] = 0x78, 3378c10e0baSHervé Poussineau [Q_KEY_CODE_F12] = 0x07, 3388c10e0baSHervé Poussineau /* special handling for Q_KEY_CODE_PRINT */ 3398c10e0baSHervé Poussineau [Q_KEY_CODE_SCROLL_LOCK] = 0x7e, 3408c10e0baSHervé Poussineau /* special handling for Q_KEY_CODE_PAUSE */ 3418c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_LEFT] = 0x54, 3428c10e0baSHervé Poussineau [Q_KEY_CODE_INSERT] = 0xe070, 3438c10e0baSHervé Poussineau [Q_KEY_CODE_HOME] = 0xe06c, 3448c10e0baSHervé Poussineau [Q_KEY_CODE_PGUP] = 0xe07d, 3458c10e0baSHervé Poussineau [Q_KEY_CODE_DELETE] = 0xe071, 3468c10e0baSHervé Poussineau [Q_KEY_CODE_END] = 0xe069, 3478c10e0baSHervé Poussineau [Q_KEY_CODE_PGDN] = 0xe07a, 3488c10e0baSHervé Poussineau [Q_KEY_CODE_UP] = 0xe075, 3498c10e0baSHervé Poussineau [Q_KEY_CODE_LEFT] = 0xe06b, 3508c10e0baSHervé Poussineau [Q_KEY_CODE_DOWN] = 0xe072, 3518c10e0baSHervé Poussineau [Q_KEY_CODE_RIGHT] = 0xe074, 3528c10e0baSHervé Poussineau [Q_KEY_CODE_NUM_LOCK] = 0x77, 3538c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DIVIDE] = 0xe04a, 3548c10e0baSHervé Poussineau [Q_KEY_CODE_KP_MULTIPLY] = 0x7c, 3558c10e0baSHervé Poussineau [Q_KEY_CODE_KP_SUBTRACT] = 0x7b, 3568c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ADD] = 0x79, 3578c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ENTER] = 0xe05a, 3588c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DECIMAL] = 0x71, 3598c10e0baSHervé Poussineau [Q_KEY_CODE_KP_0] = 0x70, 3608c10e0baSHervé Poussineau [Q_KEY_CODE_KP_1] = 0x69, 3618c10e0baSHervé Poussineau [Q_KEY_CODE_KP_2] = 0x72, 3628c10e0baSHervé Poussineau [Q_KEY_CODE_KP_3] = 0x7a, 3638c10e0baSHervé Poussineau [Q_KEY_CODE_KP_4] = 0x6b, 3648c10e0baSHervé Poussineau [Q_KEY_CODE_KP_5] = 0x73, 3658c10e0baSHervé Poussineau [Q_KEY_CODE_KP_6] = 0x74, 3668c10e0baSHervé Poussineau [Q_KEY_CODE_KP_7] = 0x6c, 3678c10e0baSHervé Poussineau [Q_KEY_CODE_KP_8] = 0x75, 3688c10e0baSHervé Poussineau [Q_KEY_CODE_KP_9] = 0x7d, 3698c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_RIGHT] = 0x5b, 3708c10e0baSHervé Poussineau [Q_KEY_CODE_SEMICOLON] = 0x4c, 3718c10e0baSHervé Poussineau [Q_KEY_CODE_APOSTROPHE] = 0x52, 3728c10e0baSHervé Poussineau [Q_KEY_CODE_COMMA] = 0x41, 3738c10e0baSHervé Poussineau [Q_KEY_CODE_DOT] = 0x49, 3748c10e0baSHervé Poussineau [Q_KEY_CODE_SLASH] = 0x4a, 3758c10e0baSHervé Poussineau 3768c10e0baSHervé Poussineau [Q_KEY_CODE_POWER] = 0x0e37, 3778c10e0baSHervé Poussineau [Q_KEY_CODE_SLEEP] = 0x0e3f, 3788c10e0baSHervé Poussineau [Q_KEY_CODE_WAKE] = 0x0e5e, 3798c10e0baSHervé Poussineau 3808c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIONEXT] = 0xe04d, 3818c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOPREV] = 0xe015, 3828c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOSTOP] = 0xe03b, 3838c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOPLAY] = 0xe034, 3848c10e0baSHervé Poussineau [Q_KEY_CODE_AUDIOMUTE] = 0xe023, 3858c10e0baSHervé Poussineau [Q_KEY_CODE_VOLUMEUP] = 0xe032, 3868c10e0baSHervé Poussineau [Q_KEY_CODE_VOLUMEDOWN] = 0xe021, 3878c10e0baSHervé Poussineau [Q_KEY_CODE_MEDIASELECT] = 0xe050, 3888c10e0baSHervé Poussineau [Q_KEY_CODE_MAIL] = 0xe048, 3898c10e0baSHervé Poussineau [Q_KEY_CODE_CALCULATOR] = 0xe02b, 3908c10e0baSHervé Poussineau [Q_KEY_CODE_COMPUTER] = 0xe040, 391103dce8fSGerd Hoffmann [Q_KEY_CODE_FIND] = 0xe010, 3928c10e0baSHervé Poussineau [Q_KEY_CODE_AC_HOME] = 0xe03a, 3938c10e0baSHervé Poussineau [Q_KEY_CODE_AC_BACK] = 0xe038, 3948c10e0baSHervé Poussineau [Q_KEY_CODE_AC_FORWARD] = 0xe030, 395103dce8fSGerd Hoffmann [Q_KEY_CODE_STOP] = 0xe028, 3968c10e0baSHervé Poussineau [Q_KEY_CODE_AC_REFRESH] = 0xe020, 3978c10e0baSHervé Poussineau [Q_KEY_CODE_AC_BOOKMARKS] = 0xe018, 3988c10e0baSHervé Poussineau 3998c10e0baSHervé Poussineau [Q_KEY_CODE_ASTERISK] = 0x7c, 4008c10e0baSHervé Poussineau [Q_KEY_CODE_LESS] = 0x61, 4018c10e0baSHervé Poussineau [Q_KEY_CODE_SYSRQ] = 0x7f, 4028c10e0baSHervé Poussineau [Q_KEY_CODE_RO] = 0x51, 403e9346441SOGAWA Hirofumi [Q_KEY_CODE_HIRAGANA] = 0x13, 404e9346441SOGAWA Hirofumi [Q_KEY_CODE_HENKAN] = 0x64, 405e9346441SOGAWA Hirofumi [Q_KEY_CODE_YEN] = 0x6a, 4068c10e0baSHervé Poussineau [Q_KEY_CODE_KP_COMMA] = 0x6d, 4078c10e0baSHervé Poussineau }; 4088c10e0baSHervé Poussineau 4098c10e0baSHervé Poussineau static const uint16_t qcode_to_keycode_set3[Q_KEY_CODE__MAX] = { 4108c10e0baSHervé Poussineau [0 ... Q_KEY_CODE__MAX - 1] = 0, 4118c10e0baSHervé Poussineau 4128c10e0baSHervé Poussineau [Q_KEY_CODE_A] = 0x1c, 4138c10e0baSHervé Poussineau [Q_KEY_CODE_B] = 0x32, 4148c10e0baSHervé Poussineau [Q_KEY_CODE_C] = 0x21, 4158c10e0baSHervé Poussineau [Q_KEY_CODE_D] = 0x23, 4168c10e0baSHervé Poussineau [Q_KEY_CODE_E] = 0x24, 4178c10e0baSHervé Poussineau [Q_KEY_CODE_F] = 0x2b, 4188c10e0baSHervé Poussineau [Q_KEY_CODE_G] = 0x34, 4198c10e0baSHervé Poussineau [Q_KEY_CODE_H] = 0x33, 4208c10e0baSHervé Poussineau [Q_KEY_CODE_I] = 0x43, 4218c10e0baSHervé Poussineau [Q_KEY_CODE_J] = 0x3b, 4228c10e0baSHervé Poussineau [Q_KEY_CODE_K] = 0x42, 4238c10e0baSHervé Poussineau [Q_KEY_CODE_L] = 0x4b, 4248c10e0baSHervé Poussineau [Q_KEY_CODE_M] = 0x3a, 4258c10e0baSHervé Poussineau [Q_KEY_CODE_N] = 0x31, 4268c10e0baSHervé Poussineau [Q_KEY_CODE_O] = 0x44, 4278c10e0baSHervé Poussineau [Q_KEY_CODE_P] = 0x4d, 4288c10e0baSHervé Poussineau [Q_KEY_CODE_Q] = 0x15, 4298c10e0baSHervé Poussineau [Q_KEY_CODE_R] = 0x2d, 4308c10e0baSHervé Poussineau [Q_KEY_CODE_S] = 0x1b, 4318c10e0baSHervé Poussineau [Q_KEY_CODE_T] = 0x2c, 4328c10e0baSHervé Poussineau [Q_KEY_CODE_U] = 0x3c, 4338c10e0baSHervé Poussineau [Q_KEY_CODE_V] = 0x2a, 4348c10e0baSHervé Poussineau [Q_KEY_CODE_W] = 0x1d, 4358c10e0baSHervé Poussineau [Q_KEY_CODE_X] = 0x22, 4368c10e0baSHervé Poussineau [Q_KEY_CODE_Y] = 0x35, 4378c10e0baSHervé Poussineau [Q_KEY_CODE_Z] = 0x1a, 4388c10e0baSHervé Poussineau [Q_KEY_CODE_0] = 0x45, 4398c10e0baSHervé Poussineau [Q_KEY_CODE_1] = 0x16, 4408c10e0baSHervé Poussineau [Q_KEY_CODE_2] = 0x1e, 4418c10e0baSHervé Poussineau [Q_KEY_CODE_3] = 0x26, 4428c10e0baSHervé Poussineau [Q_KEY_CODE_4] = 0x25, 4438c10e0baSHervé Poussineau [Q_KEY_CODE_5] = 0x2e, 4448c10e0baSHervé Poussineau [Q_KEY_CODE_6] = 0x36, 4458c10e0baSHervé Poussineau [Q_KEY_CODE_7] = 0x3d, 4468c10e0baSHervé Poussineau [Q_KEY_CODE_8] = 0x3e, 4478c10e0baSHervé Poussineau [Q_KEY_CODE_9] = 0x46, 4488c10e0baSHervé Poussineau [Q_KEY_CODE_GRAVE_ACCENT] = 0x0e, 4498c10e0baSHervé Poussineau [Q_KEY_CODE_MINUS] = 0x4e, 4508c10e0baSHervé Poussineau [Q_KEY_CODE_EQUAL] = 0x55, 4518c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSLASH] = 0x5c, 4528c10e0baSHervé Poussineau [Q_KEY_CODE_BACKSPACE] = 0x66, 4538c10e0baSHervé Poussineau [Q_KEY_CODE_SPC] = 0x29, 4548c10e0baSHervé Poussineau [Q_KEY_CODE_TAB] = 0x0d, 4558c10e0baSHervé Poussineau [Q_KEY_CODE_CAPS_LOCK] = 0x14, 4568c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT] = 0x12, 4578c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL] = 0x11, 4588c10e0baSHervé Poussineau [Q_KEY_CODE_META_L] = 0x8b, 4598c10e0baSHervé Poussineau [Q_KEY_CODE_ALT] = 0x19, 4608c10e0baSHervé Poussineau [Q_KEY_CODE_SHIFT_R] = 0x59, 4618c10e0baSHervé Poussineau [Q_KEY_CODE_CTRL_R] = 0x58, 4628c10e0baSHervé Poussineau [Q_KEY_CODE_META_R] = 0x8c, 4638c10e0baSHervé Poussineau [Q_KEY_CODE_ALT_R] = 0x39, 4648c10e0baSHervé Poussineau [Q_KEY_CODE_MENU] = 0x8d, 4658c10e0baSHervé Poussineau [Q_KEY_CODE_RET] = 0x5a, 4668c10e0baSHervé Poussineau [Q_KEY_CODE_ESC] = 0x08, 4678c10e0baSHervé Poussineau [Q_KEY_CODE_F1] = 0x07, 4688c10e0baSHervé Poussineau [Q_KEY_CODE_F2] = 0x0f, 4698c10e0baSHervé Poussineau [Q_KEY_CODE_F3] = 0x17, 4708c10e0baSHervé Poussineau [Q_KEY_CODE_F4] = 0x1f, 4718c10e0baSHervé Poussineau [Q_KEY_CODE_F5] = 0x27, 4728c10e0baSHervé Poussineau [Q_KEY_CODE_F6] = 0x2f, 4738c10e0baSHervé Poussineau [Q_KEY_CODE_F7] = 0x37, 4748c10e0baSHervé Poussineau [Q_KEY_CODE_F8] = 0x3f, 4758c10e0baSHervé Poussineau [Q_KEY_CODE_F9] = 0x47, 4768c10e0baSHervé Poussineau [Q_KEY_CODE_F10] = 0x4f, 4778c10e0baSHervé Poussineau [Q_KEY_CODE_F11] = 0x56, 4788c10e0baSHervé Poussineau [Q_KEY_CODE_F12] = 0x5e, 4798c10e0baSHervé Poussineau [Q_KEY_CODE_PRINT] = 0x57, 4808c10e0baSHervé Poussineau [Q_KEY_CODE_SCROLL_LOCK] = 0x5f, 4818c10e0baSHervé Poussineau [Q_KEY_CODE_PAUSE] = 0x62, 4828c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_LEFT] = 0x54, 4838c10e0baSHervé Poussineau [Q_KEY_CODE_INSERT] = 0x67, 4848c10e0baSHervé Poussineau [Q_KEY_CODE_HOME] = 0x6e, 4858c10e0baSHervé Poussineau [Q_KEY_CODE_PGUP] = 0x6f, 4868c10e0baSHervé Poussineau [Q_KEY_CODE_DELETE] = 0x64, 4878c10e0baSHervé Poussineau [Q_KEY_CODE_END] = 0x65, 4888c10e0baSHervé Poussineau [Q_KEY_CODE_PGDN] = 0x6d, 4898c10e0baSHervé Poussineau [Q_KEY_CODE_UP] = 0x63, 4908c10e0baSHervé Poussineau [Q_KEY_CODE_LEFT] = 0x61, 4918c10e0baSHervé Poussineau [Q_KEY_CODE_DOWN] = 0x60, 4928c10e0baSHervé Poussineau [Q_KEY_CODE_RIGHT] = 0x6a, 4938c10e0baSHervé Poussineau [Q_KEY_CODE_NUM_LOCK] = 0x76, 4948c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DIVIDE] = 0x4a, 4958c10e0baSHervé Poussineau [Q_KEY_CODE_KP_MULTIPLY] = 0x7e, 4968c10e0baSHervé Poussineau [Q_KEY_CODE_KP_SUBTRACT] = 0x4e, 4978c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ADD] = 0x7c, 4988c10e0baSHervé Poussineau [Q_KEY_CODE_KP_ENTER] = 0x79, 4998c10e0baSHervé Poussineau [Q_KEY_CODE_KP_DECIMAL] = 0x71, 5008c10e0baSHervé Poussineau [Q_KEY_CODE_KP_0] = 0x70, 5018c10e0baSHervé Poussineau [Q_KEY_CODE_KP_1] = 0x69, 5028c10e0baSHervé Poussineau [Q_KEY_CODE_KP_2] = 0x72, 5038c10e0baSHervé Poussineau [Q_KEY_CODE_KP_3] = 0x7a, 5048c10e0baSHervé Poussineau [Q_KEY_CODE_KP_4] = 0x6b, 5058c10e0baSHervé Poussineau [Q_KEY_CODE_KP_5] = 0x73, 5068c10e0baSHervé Poussineau [Q_KEY_CODE_KP_6] = 0x74, 5078c10e0baSHervé Poussineau [Q_KEY_CODE_KP_7] = 0x6c, 5088c10e0baSHervé Poussineau [Q_KEY_CODE_KP_8] = 0x75, 5098c10e0baSHervé Poussineau [Q_KEY_CODE_KP_9] = 0x7d, 5108c10e0baSHervé Poussineau [Q_KEY_CODE_BRACKET_RIGHT] = 0x5b, 5118c10e0baSHervé Poussineau [Q_KEY_CODE_SEMICOLON] = 0x4c, 5128c10e0baSHervé Poussineau [Q_KEY_CODE_APOSTROPHE] = 0x52, 5138c10e0baSHervé Poussineau [Q_KEY_CODE_COMMA] = 0x41, 5148c10e0baSHervé Poussineau [Q_KEY_CODE_DOT] = 0x49, 5158c10e0baSHervé Poussineau [Q_KEY_CODE_SLASH] = 0x4a, 516e9346441SOGAWA Hirofumi 517e9346441SOGAWA Hirofumi [Q_KEY_CODE_HIRAGANA] = 0x87, 518e9346441SOGAWA Hirofumi [Q_KEY_CODE_HENKAN] = 0x86, 519e9346441SOGAWA Hirofumi [Q_KEY_CODE_YEN] = 0x5d, 5207096a96dSRoy Tam }; 521f94f5d71Spbrook 52257d5c005SHervé Poussineau static uint8_t translate_table[256] = { 52357d5c005SHervé Poussineau 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 52457d5c005SHervé Poussineau 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, 52557d5c005SHervé Poussineau 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, 52657d5c005SHervé Poussineau 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, 52757d5c005SHervé Poussineau 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, 52857d5c005SHervé Poussineau 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, 52957d5c005SHervé Poussineau 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, 53057d5c005SHervé Poussineau 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, 53157d5c005SHervé Poussineau 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, 53257d5c005SHervé Poussineau 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, 53357d5c005SHervé Poussineau 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, 53457d5c005SHervé Poussineau 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, 53557d5c005SHervé Poussineau 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, 53657d5c005SHervé Poussineau 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, 53757d5c005SHervé Poussineau 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, 53857d5c005SHervé Poussineau 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, 53957d5c005SHervé Poussineau 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, 54057d5c005SHervé Poussineau 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 54157d5c005SHervé Poussineau 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 54257d5c005SHervé Poussineau 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 54357d5c005SHervé Poussineau 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 54457d5c005SHervé Poussineau 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 54557d5c005SHervé Poussineau 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 54657d5c005SHervé Poussineau 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 54757d5c005SHervé Poussineau 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 54857d5c005SHervé Poussineau 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 54957d5c005SHervé Poussineau 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 55057d5c005SHervé Poussineau 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 55157d5c005SHervé Poussineau 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 55257d5c005SHervé Poussineau 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 55357d5c005SHervé Poussineau 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 55457d5c005SHervé Poussineau 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 55557d5c005SHervé Poussineau }; 55657d5c005SHervé Poussineau 557620775d1SDaniel P. Berrange static unsigned int ps2_modifier_bit(QKeyCode key) 558620775d1SDaniel P. Berrange { 559620775d1SDaniel P. Berrange switch (key) { 560620775d1SDaniel P. Berrange case Q_KEY_CODE_CTRL: 561620775d1SDaniel P. Berrange return MOD_CTRL_L; 562620775d1SDaniel P. Berrange case Q_KEY_CODE_CTRL_R: 563620775d1SDaniel P. Berrange return MOD_CTRL_R; 564620775d1SDaniel P. Berrange case Q_KEY_CODE_SHIFT: 565620775d1SDaniel P. Berrange return MOD_SHIFT_L; 566620775d1SDaniel P. Berrange case Q_KEY_CODE_SHIFT_R: 567620775d1SDaniel P. Berrange return MOD_SHIFT_R; 568620775d1SDaniel P. Berrange case Q_KEY_CODE_ALT: 569620775d1SDaniel P. Berrange return MOD_ALT_L; 570620775d1SDaniel P. Berrange case Q_KEY_CODE_ALT_R: 571620775d1SDaniel P. Berrange return MOD_ALT_R; 572620775d1SDaniel P. Berrange default: 573620775d1SDaniel P. Berrange return 0; 574620775d1SDaniel P. Berrange } 575620775d1SDaniel P. Berrange } 576620775d1SDaniel P. Berrange 577954ee55bSGerd Hoffmann static void ps2_reset_queue(PS2State *s) 578954ee55bSGerd Hoffmann { 579954ee55bSGerd Hoffmann PS2Queue *q = &s->queue; 580954ee55bSGerd Hoffmann 581954ee55bSGerd Hoffmann q->rptr = 0; 582954ee55bSGerd Hoffmann q->wptr = 0; 583954ee55bSGerd Hoffmann q->count = 0; 584954ee55bSGerd Hoffmann } 585954ee55bSGerd Hoffmann 5868498bb8dSGerd Hoffmann void ps2_queue(PS2State *s, int b) 5870e43e99cSbellard { 5880e43e99cSbellard PS2Queue *q = &s->queue; 5890e43e99cSbellard 5902858ab09SGonglei if (q->count >= PS2_QUEUE_SIZE - 1) 5910e43e99cSbellard return; 5920e43e99cSbellard q->data[q->wptr] = b; 5930e43e99cSbellard if (++q->wptr == PS2_QUEUE_SIZE) 5940e43e99cSbellard q->wptr = 0; 5950e43e99cSbellard q->count++; 5960e43e99cSbellard s->update_irq(s->update_arg, 1); 5970e43e99cSbellard } 5980e43e99cSbellard 59957d5c005SHervé Poussineau /* keycode is the untranslated scancode in the current scancode set. */ 6000e43e99cSbellard static void ps2_put_keycode(void *opaque, int keycode) 6010e43e99cSbellard { 602f94f5d71Spbrook PS2KbdState *s = opaque; 603e7d93956Saurel32 6045edab03dSDon Koch trace_ps2_put_keycode(opaque, keycode); 605fd214d18SGerd Hoffmann qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); 60657d5c005SHervé Poussineau 60757d5c005SHervé Poussineau if (s->translate) { 60857d5c005SHervé Poussineau if (keycode == 0xf0) { 60957d5c005SHervé Poussineau s->need_high_bit = true; 61057d5c005SHervé Poussineau } else if (s->need_high_bit) { 61157d5c005SHervé Poussineau ps2_queue(&s->common, translate_table[keycode] | 0x80); 61257d5c005SHervé Poussineau s->need_high_bit = false; 61357d5c005SHervé Poussineau } else { 61457d5c005SHervé Poussineau ps2_queue(&s->common, translate_table[keycode]); 6157096a96dSRoy Tam } 61657d5c005SHervé Poussineau } else { 6170e43e99cSbellard ps2_queue(&s->common, keycode); 6180e43e99cSbellard } 61957d5c005SHervé Poussineau } 6200e43e99cSbellard 62166e6536eSGerd Hoffmann static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src, 62266e6536eSGerd Hoffmann InputEvent *evt) 62366e6536eSGerd Hoffmann { 62466e6536eSGerd Hoffmann PS2KbdState *s = (PS2KbdState *)dev; 62532bafa8fSEric Blake InputKeyEvent *key = evt->u.key.data; 6268c10e0baSHervé Poussineau int qcode; 6278c10e0baSHervé Poussineau uint16_t keycode; 628620775d1SDaniel P. Berrange int mod; 62966e6536eSGerd Hoffmann 63066e6536eSGerd Hoffmann qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); 6318c10e0baSHervé Poussineau assert(evt->type == INPUT_EVENT_KIND_KEY); 6328c10e0baSHervé Poussineau qcode = qemu_input_key_value_to_qcode(key->key); 63357d5c005SHervé Poussineau 634620775d1SDaniel P. Berrange mod = ps2_modifier_bit(qcode); 635620775d1SDaniel P. Berrange trace_ps2_keyboard_event(s, qcode, key->down, mod, s->modifiers); 636620775d1SDaniel P. Berrange if (key->down) { 637620775d1SDaniel P. Berrange s->modifiers |= mod; 638620775d1SDaniel P. Berrange } else { 639620775d1SDaniel P. Berrange s->modifiers &= ~mod; 640620775d1SDaniel P. Berrange } 641620775d1SDaniel P. Berrange 6428c10e0baSHervé Poussineau if (s->scancode_set == 1) { 6438c10e0baSHervé Poussineau if (qcode == Q_KEY_CODE_PAUSE) { 64429fd23a5SDaniel P. Berrange if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) { 64529fd23a5SDaniel P. Berrange if (key->down) { 64629fd23a5SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 64729fd23a5SDaniel P. Berrange ps2_put_keycode(s, 0x46); 64829fd23a5SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 64929fd23a5SDaniel P. Berrange ps2_put_keycode(s, 0xc6); 65029fd23a5SDaniel P. Berrange } 65129fd23a5SDaniel P. Berrange } else { 6528c10e0baSHervé Poussineau if (key->down) { 6538c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe1); 6548c10e0baSHervé Poussineau ps2_put_keycode(s, 0x1d); 6558c10e0baSHervé Poussineau ps2_put_keycode(s, 0x45); 656927f0425SDaniel P. Berrange ps2_put_keycode(s, 0xe1); 6578c10e0baSHervé Poussineau ps2_put_keycode(s, 0x9d); 6588c10e0baSHervé Poussineau ps2_put_keycode(s, 0xc5); 6598c10e0baSHervé Poussineau } 66029fd23a5SDaniel P. Berrange } 6618c10e0baSHervé Poussineau } else if (qcode == Q_KEY_CODE_PRINT) { 662620775d1SDaniel P. Berrange if (s->modifiers & MOD_ALT_L) { 663620775d1SDaniel P. Berrange if (key->down) { 664620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xb8); 665620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x38); 666620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x54); 667620775d1SDaniel P. Berrange } else { 668620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xd4); 669620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xb8); 670620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x38); 671620775d1SDaniel P. Berrange } 672620775d1SDaniel P. Berrange } else if (s->modifiers & MOD_ALT_R) { 673620775d1SDaniel P. Berrange if (key->down) { 674620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 675620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xb8); 676620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 677620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x38); 678620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x54); 679620775d1SDaniel P. Berrange } else { 680620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xd4); 681620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 682620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xb8); 683620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 684620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x38); 685620775d1SDaniel P. Berrange } 6868f63458fSDaniel P. Berrange } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L | 6878f63458fSDaniel P. Berrange MOD_SHIFT_R | MOD_CTRL_R)) { 6888f63458fSDaniel P. Berrange if (key->down) { 6898f63458fSDaniel P. Berrange ps2_put_keycode(s, 0xe0); 6908f63458fSDaniel P. Berrange ps2_put_keycode(s, 0x37); 6918f63458fSDaniel P. Berrange } else { 6928f63458fSDaniel P. Berrange ps2_put_keycode(s, 0xe0); 6938f63458fSDaniel P. Berrange ps2_put_keycode(s, 0xb7); 6948f63458fSDaniel P. Berrange } 695620775d1SDaniel P. Berrange } else { 6968c10e0baSHervé Poussineau if (key->down) { 6978c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 6988c10e0baSHervé Poussineau ps2_put_keycode(s, 0x2a); 6998c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 7008c10e0baSHervé Poussineau ps2_put_keycode(s, 0x37); 7018c10e0baSHervé Poussineau } else { 7028c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 7038c10e0baSHervé Poussineau ps2_put_keycode(s, 0xb7); 7048c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 7058c10e0baSHervé Poussineau ps2_put_keycode(s, 0xaa); 7068c10e0baSHervé Poussineau } 707620775d1SDaniel P. Berrange } 7088c10e0baSHervé Poussineau } else { 7098c10e0baSHervé Poussineau keycode = qcode_to_keycode_set1[qcode]; 7108c10e0baSHervé Poussineau if (keycode) { 7118c10e0baSHervé Poussineau if (keycode & 0xff00) { 7128c10e0baSHervé Poussineau ps2_put_keycode(s, keycode >> 8); 7138c10e0baSHervé Poussineau } 7148c10e0baSHervé Poussineau if (!key->down) { 7158c10e0baSHervé Poussineau keycode |= 0x80; 7168c10e0baSHervé Poussineau } 7178c10e0baSHervé Poussineau ps2_put_keycode(s, keycode & 0xff); 7188c10e0baSHervé Poussineau } else { 719ec044a80SHervé Poussineau qemu_log_mask(LOG_UNIMP, 720ec044a80SHervé Poussineau "ps2: ignoring key with qcode %d\n", qcode); 7218c10e0baSHervé Poussineau } 7228c10e0baSHervé Poussineau } 7238c10e0baSHervé Poussineau } else if (s->scancode_set == 2) { 7248c10e0baSHervé Poussineau if (qcode == Q_KEY_CODE_PAUSE) { 72529fd23a5SDaniel P. Berrange if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) { 72629fd23a5SDaniel P. Berrange if (key->down) { 72729fd23a5SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 72829fd23a5SDaniel P. Berrange ps2_put_keycode(s, 0x7e); 72929fd23a5SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 73029fd23a5SDaniel P. Berrange ps2_put_keycode(s, 0xf0); 73129fd23a5SDaniel P. Berrange ps2_put_keycode(s, 0x7e); 73229fd23a5SDaniel P. Berrange } 73329fd23a5SDaniel P. Berrange } else { 7348c10e0baSHervé Poussineau if (key->down) { 7358c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe1); 7368c10e0baSHervé Poussineau ps2_put_keycode(s, 0x14); 7378c10e0baSHervé Poussineau ps2_put_keycode(s, 0x77); 7388c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe1); 7398c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 7408c10e0baSHervé Poussineau ps2_put_keycode(s, 0x14); 7418c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 7428c10e0baSHervé Poussineau ps2_put_keycode(s, 0x77); 7438c10e0baSHervé Poussineau } 74429fd23a5SDaniel P. Berrange } 7458c10e0baSHervé Poussineau } else if (qcode == Q_KEY_CODE_PRINT) { 746620775d1SDaniel P. Berrange if (s->modifiers & MOD_ALT_L) { 747620775d1SDaniel P. Berrange if (key->down) { 748620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xf0); 749620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x11); 750620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x11); 751620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x84); 752620775d1SDaniel P. Berrange } else { 753620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xf0); 754620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x84); 755620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xf0); 756620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x11); 757620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x11); 758620775d1SDaniel P. Berrange } 759620775d1SDaniel P. Berrange } else if (s->modifiers & MOD_ALT_R) { 760620775d1SDaniel P. Berrange if (key->down) { 761620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 762620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xf0); 763620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x11); 764620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 765620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x11); 766620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x84); 767620775d1SDaniel P. Berrange } else { 768620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xf0); 769620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x84); 770620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 771620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xf0); 772620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x11); 773620775d1SDaniel P. Berrange ps2_put_keycode(s, 0xe0); 774620775d1SDaniel P. Berrange ps2_put_keycode(s, 0x11); 775620775d1SDaniel P. Berrange } 7768f63458fSDaniel P. Berrange } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L | 7778f63458fSDaniel P. Berrange MOD_SHIFT_R | MOD_CTRL_R)) { 7788f63458fSDaniel P. Berrange if (key->down) { 7798f63458fSDaniel P. Berrange ps2_put_keycode(s, 0xe0); 7808f63458fSDaniel P. Berrange ps2_put_keycode(s, 0x7c); 7818f63458fSDaniel P. Berrange } else { 7828f63458fSDaniel P. Berrange ps2_put_keycode(s, 0xe0); 7838f63458fSDaniel P. Berrange ps2_put_keycode(s, 0xf0); 7848f63458fSDaniel P. Berrange ps2_put_keycode(s, 0x7c); 7858f63458fSDaniel P. Berrange } 786620775d1SDaniel P. Berrange } else { 7878c10e0baSHervé Poussineau if (key->down) { 7888c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 7898c10e0baSHervé Poussineau ps2_put_keycode(s, 0x12); 7908c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 7918c10e0baSHervé Poussineau ps2_put_keycode(s, 0x7c); 7928c10e0baSHervé Poussineau } else { 7938c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 7948c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 7958c10e0baSHervé Poussineau ps2_put_keycode(s, 0x7c); 7968c10e0baSHervé Poussineau ps2_put_keycode(s, 0xe0); 7978c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 7988c10e0baSHervé Poussineau ps2_put_keycode(s, 0x12); 7998c10e0baSHervé Poussineau } 800620775d1SDaniel P. Berrange } 8018c10e0baSHervé Poussineau } else { 8028c10e0baSHervé Poussineau keycode = qcode_to_keycode_set2[qcode]; 8038c10e0baSHervé Poussineau if (keycode) { 8048c10e0baSHervé Poussineau if (keycode & 0xff00) { 8058c10e0baSHervé Poussineau ps2_put_keycode(s, keycode >> 8); 8068c10e0baSHervé Poussineau } 8078c10e0baSHervé Poussineau if (!key->down) { 8088c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 8098c10e0baSHervé Poussineau } 8108c10e0baSHervé Poussineau ps2_put_keycode(s, keycode & 0xff); 81157d5c005SHervé Poussineau } else { 812ec044a80SHervé Poussineau qemu_log_mask(LOG_UNIMP, 813ec044a80SHervé Poussineau "ps2: ignoring key with qcode %d\n", qcode); 81457d5c005SHervé Poussineau } 81557d5c005SHervé Poussineau } 81657d5c005SHervé Poussineau } else if (s->scancode_set == 3) { 8178c10e0baSHervé Poussineau keycode = qcode_to_keycode_set3[qcode]; 8188c10e0baSHervé Poussineau if (keycode) { 8198c10e0baSHervé Poussineau /* FIXME: break code should be configured on a key by key basis */ 8208c10e0baSHervé Poussineau if (!key->down) { 8218c10e0baSHervé Poussineau ps2_put_keycode(s, 0xf0); 82257d5c005SHervé Poussineau } 82357d5c005SHervé Poussineau ps2_put_keycode(s, keycode); 8248c10e0baSHervé Poussineau } else { 825ec044a80SHervé Poussineau qemu_log_mask(LOG_UNIMP, 826ec044a80SHervé Poussineau "ps2: ignoring key with qcode %d\n", qcode); 8278c10e0baSHervé Poussineau } 82866e6536eSGerd Hoffmann } 82966e6536eSGerd Hoffmann } 83066e6536eSGerd Hoffmann 8318498bb8dSGerd Hoffmann uint32_t ps2_read_data(PS2State *s) 8320e43e99cSbellard { 8330e43e99cSbellard PS2Queue *q; 8340e43e99cSbellard int val, index; 8350e43e99cSbellard 8368498bb8dSGerd Hoffmann trace_ps2_read_data(s); 8370e43e99cSbellard q = &s->queue; 8380e43e99cSbellard if (q->count == 0) { 8390e43e99cSbellard /* NOTE: if no data left, we return the last keyboard one 8400e43e99cSbellard (needed for EMM386) */ 8410e43e99cSbellard /* XXX: need a timer to do things correctly */ 8420e43e99cSbellard index = q->rptr - 1; 8430e43e99cSbellard if (index < 0) 8440e43e99cSbellard index = PS2_QUEUE_SIZE - 1; 8450e43e99cSbellard val = q->data[index]; 8460e43e99cSbellard } else { 8470e43e99cSbellard val = q->data[q->rptr]; 8480e43e99cSbellard if (++q->rptr == PS2_QUEUE_SIZE) 8490e43e99cSbellard q->rptr = 0; 8500e43e99cSbellard q->count--; 8510e43e99cSbellard /* reading deasserts IRQ */ 8520e43e99cSbellard s->update_irq(s->update_arg, 0); 8530e43e99cSbellard /* reassert IRQs if data left */ 8540e43e99cSbellard s->update_irq(s->update_arg, q->count != 0); 8550e43e99cSbellard } 8560e43e99cSbellard return val; 8570e43e99cSbellard } 8580e43e99cSbellard 8597f540ab5SChristophe Fergeau static void ps2_set_ledstate(PS2KbdState *s, int ledstate) 8607f540ab5SChristophe Fergeau { 8615edab03dSDon Koch trace_ps2_set_ledstate(s, ledstate); 8627f540ab5SChristophe Fergeau s->ledstate = ledstate; 8637f540ab5SChristophe Fergeau kbd_put_ledstate(ledstate); 8647f540ab5SChristophe Fergeau } 8657f540ab5SChristophe Fergeau 8660e43e99cSbellard static void ps2_reset_keyboard(PS2KbdState *s) 8670e43e99cSbellard { 8685edab03dSDon Koch trace_ps2_reset_keyboard(s); 8690e43e99cSbellard s->scan_enabled = 1; 870e7d93956Saurel32 s->scancode_set = 2; 8716e24ee0cSGerd Hoffmann ps2_reset_queue(&s->common); 8727f540ab5SChristophe Fergeau ps2_set_ledstate(s, 0); 8730e43e99cSbellard } 8740e43e99cSbellard 8750e43e99cSbellard void ps2_write_keyboard(void *opaque, int val) 8760e43e99cSbellard { 8770e43e99cSbellard PS2KbdState *s = (PS2KbdState *)opaque; 8780e43e99cSbellard 8795edab03dSDon Koch trace_ps2_write_keyboard(opaque, val); 8800e43e99cSbellard switch(s->common.write_cmd) { 8810e43e99cSbellard default: 8820e43e99cSbellard case -1: 8830e43e99cSbellard switch(val) { 8840e43e99cSbellard case 0x00: 8850e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 8860e43e99cSbellard break; 8870e43e99cSbellard case 0x05: 8880e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_RESEND); 8890e43e99cSbellard break; 8900e43e99cSbellard case KBD_CMD_GET_ID: 8910e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 892e7d93956Saurel32 /* We emulate a MF2 AT keyboard here */ 89335c4d671Saurel32 ps2_queue(&s->common, KBD_REPLY_ID); 89435c4d671Saurel32 if (s->translate) 89535c4d671Saurel32 ps2_queue(&s->common, 0x41); 89635c4d671Saurel32 else 89735c4d671Saurel32 ps2_queue(&s->common, 0x83); 8980e43e99cSbellard break; 8990e43e99cSbellard case KBD_CMD_ECHO: 9000e43e99cSbellard ps2_queue(&s->common, KBD_CMD_ECHO); 9010e43e99cSbellard break; 9020e43e99cSbellard case KBD_CMD_ENABLE: 9030e43e99cSbellard s->scan_enabled = 1; 9040e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 9050e43e99cSbellard break; 906e7d93956Saurel32 case KBD_CMD_SCANCODE: 9070e43e99cSbellard case KBD_CMD_SET_LEDS: 9080e43e99cSbellard case KBD_CMD_SET_RATE: 9090e43e99cSbellard s->common.write_cmd = val; 9100e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 9110e43e99cSbellard break; 9120e43e99cSbellard case KBD_CMD_RESET_DISABLE: 9130e43e99cSbellard ps2_reset_keyboard(s); 9140e43e99cSbellard s->scan_enabled = 0; 9150e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 9160e43e99cSbellard break; 9170e43e99cSbellard case KBD_CMD_RESET_ENABLE: 9180e43e99cSbellard ps2_reset_keyboard(s); 9190e43e99cSbellard s->scan_enabled = 1; 9200e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 9210e43e99cSbellard break; 9220e43e99cSbellard case KBD_CMD_RESET: 9230e43e99cSbellard ps2_reset_keyboard(s); 9240e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 9250e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_POR); 9260e43e99cSbellard break; 9270e43e99cSbellard default: 92806b3611fSHervé Poussineau ps2_queue(&s->common, KBD_REPLY_RESEND); 9290e43e99cSbellard break; 9300e43e99cSbellard } 9310e43e99cSbellard break; 932e7d93956Saurel32 case KBD_CMD_SCANCODE: 933e7d93956Saurel32 if (val == 0) { 9344df23b64SHervé Poussineau ps2_queue(&s->common, KBD_REPLY_ACK); 93557d5c005SHervé Poussineau ps2_put_keycode(s, s->scancode_set); 9364df23b64SHervé Poussineau } else if (val >= 1 && val <= 3) { 937e7d93956Saurel32 s->scancode_set = val; 938e7d93956Saurel32 ps2_queue(&s->common, KBD_REPLY_ACK); 9394df23b64SHervé Poussineau } else { 9404df23b64SHervé Poussineau ps2_queue(&s->common, KBD_REPLY_RESEND); 941e7d93956Saurel32 } 942e7d93956Saurel32 s->common.write_cmd = -1; 943e7d93956Saurel32 break; 9440e43e99cSbellard case KBD_CMD_SET_LEDS: 9457f540ab5SChristophe Fergeau ps2_set_ledstate(s, val); 9460e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 9470e43e99cSbellard s->common.write_cmd = -1; 9480e43e99cSbellard break; 9490e43e99cSbellard case KBD_CMD_SET_RATE: 9500e43e99cSbellard ps2_queue(&s->common, KBD_REPLY_ACK); 9510e43e99cSbellard s->common.write_cmd = -1; 9520e43e99cSbellard break; 9530e43e99cSbellard } 9540e43e99cSbellard } 9550e43e99cSbellard 956f94f5d71Spbrook /* Set the scancode translation mode. 957f94f5d71Spbrook 0 = raw scancodes. 958f94f5d71Spbrook 1 = translated scancodes (used by qemu internally). */ 959f94f5d71Spbrook 960f94f5d71Spbrook void ps2_keyboard_set_translation(void *opaque, int mode) 961f94f5d71Spbrook { 962f94f5d71Spbrook PS2KbdState *s = (PS2KbdState *)opaque; 9635edab03dSDon Koch trace_ps2_keyboard_set_translation(opaque, mode); 964f94f5d71Spbrook s->translate = mode; 965f94f5d71Spbrook } 966f94f5d71Spbrook 9670e43e99cSbellard static void ps2_mouse_send_packet(PS2MouseState *s) 9680e43e99cSbellard { 9690e43e99cSbellard unsigned int b; 9700e43e99cSbellard int dx1, dy1, dz1; 9710e43e99cSbellard 9720e43e99cSbellard dx1 = s->mouse_dx; 9730e43e99cSbellard dy1 = s->mouse_dy; 9740e43e99cSbellard dz1 = s->mouse_dz; 9750e43e99cSbellard /* XXX: increase range to 8 bits ? */ 9760e43e99cSbellard if (dx1 > 127) 9770e43e99cSbellard dx1 = 127; 9780e43e99cSbellard else if (dx1 < -127) 9790e43e99cSbellard dx1 = -127; 9800e43e99cSbellard if (dy1 > 127) 9810e43e99cSbellard dy1 = 127; 9820e43e99cSbellard else if (dy1 < -127) 9830e43e99cSbellard dy1 = -127; 9840e43e99cSbellard b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); 9850e43e99cSbellard ps2_queue(&s->common, b); 9860e43e99cSbellard ps2_queue(&s->common, dx1 & 0xff); 9870e43e99cSbellard ps2_queue(&s->common, dy1 & 0xff); 9880e43e99cSbellard /* extra byte for IMPS/2 or IMEX */ 9890e43e99cSbellard switch(s->mouse_type) { 9900e43e99cSbellard default: 9910e43e99cSbellard break; 9920e43e99cSbellard case 3: 9930e43e99cSbellard if (dz1 > 127) 9940e43e99cSbellard dz1 = 127; 9950e43e99cSbellard else if (dz1 < -127) 9960e43e99cSbellard dz1 = -127; 9970e43e99cSbellard ps2_queue(&s->common, dz1 & 0xff); 9980e43e99cSbellard break; 9990e43e99cSbellard case 4: 10000e43e99cSbellard if (dz1 > 7) 10010e43e99cSbellard dz1 = 7; 10020e43e99cSbellard else if (dz1 < -7) 10030e43e99cSbellard dz1 = -7; 10040e43e99cSbellard b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); 10050e43e99cSbellard ps2_queue(&s->common, b); 10060e43e99cSbellard break; 10070e43e99cSbellard } 10080e43e99cSbellard 10095edab03dSDon Koch trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b); 10100e43e99cSbellard /* update deltas */ 10110e43e99cSbellard s->mouse_dx -= dx1; 10120e43e99cSbellard s->mouse_dy -= dy1; 10130e43e99cSbellard s->mouse_dz -= dz1; 10140e43e99cSbellard } 10150e43e99cSbellard 10162a766d29SGerd Hoffmann static void ps2_mouse_event(DeviceState *dev, QemuConsole *src, 10172a766d29SGerd Hoffmann InputEvent *evt) 10180e43e99cSbellard { 10197fb1cf16SEric Blake static const int bmap[INPUT_BUTTON__MAX] = { 10208b0caab0SFabian Lesniak [INPUT_BUTTON_LEFT] = PS2_MOUSE_BUTTON_LEFT, 10218b0caab0SFabian Lesniak [INPUT_BUTTON_MIDDLE] = PS2_MOUSE_BUTTON_MIDDLE, 10228b0caab0SFabian Lesniak [INPUT_BUTTON_RIGHT] = PS2_MOUSE_BUTTON_RIGHT, 10238b0caab0SFabian Lesniak [INPUT_BUTTON_SIDE] = PS2_MOUSE_BUTTON_SIDE, 10248b0caab0SFabian Lesniak [INPUT_BUTTON_EXTRA] = PS2_MOUSE_BUTTON_EXTRA, 10252a766d29SGerd Hoffmann }; 10262a766d29SGerd Hoffmann PS2MouseState *s = (PS2MouseState *)dev; 1027b5a1b443SEric Blake InputMoveEvent *move; 1028b5a1b443SEric Blake InputBtnEvent *btn; 10290e43e99cSbellard 10300e43e99cSbellard /* check if deltas are recorded when disabled */ 10310e43e99cSbellard if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) 10320e43e99cSbellard return; 10330e43e99cSbellard 1034568c73a4SEric Blake switch (evt->type) { 10352a766d29SGerd Hoffmann case INPUT_EVENT_KIND_REL: 103632bafa8fSEric Blake move = evt->u.rel.data; 1037b5a1b443SEric Blake if (move->axis == INPUT_AXIS_X) { 1038b5a1b443SEric Blake s->mouse_dx += move->value; 1039b5a1b443SEric Blake } else if (move->axis == INPUT_AXIS_Y) { 1040b5a1b443SEric Blake s->mouse_dy -= move->value; 10412a766d29SGerd Hoffmann } 10422a766d29SGerd Hoffmann break; 10430e43e99cSbellard 10442a766d29SGerd Hoffmann case INPUT_EVENT_KIND_BTN: 104532bafa8fSEric Blake btn = evt->u.btn.data; 1046b5a1b443SEric Blake if (btn->down) { 1047b5a1b443SEric Blake s->mouse_buttons |= bmap[btn->button]; 1048b5a1b443SEric Blake if (btn->button == INPUT_BUTTON_WHEEL_UP) { 10492a766d29SGerd Hoffmann s->mouse_dz--; 1050b5a1b443SEric Blake } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) { 10512a766d29SGerd Hoffmann s->mouse_dz++; 10522a766d29SGerd Hoffmann } 10532a766d29SGerd Hoffmann } else { 1054b5a1b443SEric Blake s->mouse_buttons &= ~bmap[btn->button]; 10552a766d29SGerd Hoffmann } 10562a766d29SGerd Hoffmann break; 10572a766d29SGerd Hoffmann 10582a766d29SGerd Hoffmann default: 10592a766d29SGerd Hoffmann /* keep gcc happy */ 10602a766d29SGerd Hoffmann break; 10612a766d29SGerd Hoffmann } 1062fd214d18SGerd Hoffmann } 1063fd214d18SGerd Hoffmann 10642a766d29SGerd Hoffmann static void ps2_mouse_sync(DeviceState *dev) 10652a766d29SGerd Hoffmann { 10662a766d29SGerd Hoffmann PS2MouseState *s = (PS2MouseState *)dev; 10672a766d29SGerd Hoffmann 10682a766d29SGerd Hoffmann if (s->mouse_buttons) { 10692a766d29SGerd Hoffmann qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); 10702a766d29SGerd Hoffmann } 10712858ab09SGonglei if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) { 10722858ab09SGonglei while (s->common.queue.count < PS2_QUEUE_SIZE - 4) { 10730e43e99cSbellard /* if not remote, send event. Multiple events are sent if 10740e43e99cSbellard too big deltas */ 10750e43e99cSbellard ps2_mouse_send_packet(s); 10760e43e99cSbellard if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) 10770e43e99cSbellard break; 10780e43e99cSbellard } 10790e43e99cSbellard } 10800e43e99cSbellard } 10810e43e99cSbellard 1082548df2acSths void ps2_mouse_fake_event(void *opaque) 1083548df2acSths { 10842a766d29SGerd Hoffmann PS2MouseState *s = opaque; 10855edab03dSDon Koch trace_ps2_mouse_fake_event(opaque); 10862a766d29SGerd Hoffmann s->mouse_dx++; 10872a766d29SGerd Hoffmann ps2_mouse_sync(opaque); 1088548df2acSths } 1089548df2acSths 10900e43e99cSbellard void ps2_write_mouse(void *opaque, int val) 10910e43e99cSbellard { 10920e43e99cSbellard PS2MouseState *s = (PS2MouseState *)opaque; 10935edab03dSDon Koch 10945edab03dSDon Koch trace_ps2_write_mouse(opaque, val); 10950e43e99cSbellard #ifdef DEBUG_MOUSE 10960e43e99cSbellard printf("kbd: write mouse 0x%02x\n", val); 10970e43e99cSbellard #endif 10980e43e99cSbellard switch(s->common.write_cmd) { 10990e43e99cSbellard default: 11000e43e99cSbellard case -1: 11010e43e99cSbellard /* mouse command */ 11020e43e99cSbellard if (s->mouse_wrap) { 11030e43e99cSbellard if (val == AUX_RESET_WRAP) { 11040e43e99cSbellard s->mouse_wrap = 0; 11050e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11060e43e99cSbellard return; 11070e43e99cSbellard } else if (val != AUX_RESET) { 11080e43e99cSbellard ps2_queue(&s->common, val); 11090e43e99cSbellard return; 11100e43e99cSbellard } 11110e43e99cSbellard } 11120e43e99cSbellard switch(val) { 11130e43e99cSbellard case AUX_SET_SCALE11: 11140e43e99cSbellard s->mouse_status &= ~MOUSE_STATUS_SCALE21; 11150e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11160e43e99cSbellard break; 11170e43e99cSbellard case AUX_SET_SCALE21: 11180e43e99cSbellard s->mouse_status |= MOUSE_STATUS_SCALE21; 11190e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11200e43e99cSbellard break; 11210e43e99cSbellard case AUX_SET_STREAM: 11220e43e99cSbellard s->mouse_status &= ~MOUSE_STATUS_REMOTE; 11230e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11240e43e99cSbellard break; 11250e43e99cSbellard case AUX_SET_WRAP: 11260e43e99cSbellard s->mouse_wrap = 1; 11270e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11280e43e99cSbellard break; 11290e43e99cSbellard case AUX_SET_REMOTE: 11300e43e99cSbellard s->mouse_status |= MOUSE_STATUS_REMOTE; 11310e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11320e43e99cSbellard break; 11330e43e99cSbellard case AUX_GET_TYPE: 11340e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11350e43e99cSbellard ps2_queue(&s->common, s->mouse_type); 11360e43e99cSbellard break; 11370e43e99cSbellard case AUX_SET_RES: 11380e43e99cSbellard case AUX_SET_SAMPLE: 11390e43e99cSbellard s->common.write_cmd = val; 11400e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11410e43e99cSbellard break; 11420e43e99cSbellard case AUX_GET_SCALE: 11430e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11440e43e99cSbellard ps2_queue(&s->common, s->mouse_status); 11450e43e99cSbellard ps2_queue(&s->common, s->mouse_resolution); 11460e43e99cSbellard ps2_queue(&s->common, s->mouse_sample_rate); 11470e43e99cSbellard break; 11480e43e99cSbellard case AUX_POLL: 11490e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11500e43e99cSbellard ps2_mouse_send_packet(s); 11510e43e99cSbellard break; 11520e43e99cSbellard case AUX_ENABLE_DEV: 11530e43e99cSbellard s->mouse_status |= MOUSE_STATUS_ENABLED; 11540e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11550e43e99cSbellard break; 11560e43e99cSbellard case AUX_DISABLE_DEV: 11570e43e99cSbellard s->mouse_status &= ~MOUSE_STATUS_ENABLED; 11580e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11590e43e99cSbellard break; 11600e43e99cSbellard case AUX_SET_DEFAULT: 11610e43e99cSbellard s->mouse_sample_rate = 100; 11620e43e99cSbellard s->mouse_resolution = 2; 11630e43e99cSbellard s->mouse_status = 0; 11640e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11650e43e99cSbellard break; 11660e43e99cSbellard case AUX_RESET: 11670e43e99cSbellard s->mouse_sample_rate = 100; 11680e43e99cSbellard s->mouse_resolution = 2; 11690e43e99cSbellard s->mouse_status = 0; 11700e43e99cSbellard s->mouse_type = 0; 11710e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 11720e43e99cSbellard ps2_queue(&s->common, 0xaa); 11730e43e99cSbellard ps2_queue(&s->common, s->mouse_type); 11740e43e99cSbellard break; 11750e43e99cSbellard default: 11760e43e99cSbellard break; 11770e43e99cSbellard } 11780e43e99cSbellard break; 11790e43e99cSbellard case AUX_SET_SAMPLE: 11800e43e99cSbellard s->mouse_sample_rate = val; 11810e43e99cSbellard /* detect IMPS/2 or IMEX */ 11820e43e99cSbellard switch(s->mouse_detect_state) { 11830e43e99cSbellard default: 11840e43e99cSbellard case 0: 11850e43e99cSbellard if (val == 200) 11860e43e99cSbellard s->mouse_detect_state = 1; 11870e43e99cSbellard break; 11880e43e99cSbellard case 1: 11890e43e99cSbellard if (val == 100) 11900e43e99cSbellard s->mouse_detect_state = 2; 11910e43e99cSbellard else if (val == 200) 11920e43e99cSbellard s->mouse_detect_state = 3; 11930e43e99cSbellard else 11940e43e99cSbellard s->mouse_detect_state = 0; 11950e43e99cSbellard break; 11960e43e99cSbellard case 2: 11970e43e99cSbellard if (val == 80) 11980e43e99cSbellard s->mouse_type = 3; /* IMPS/2 */ 11990e43e99cSbellard s->mouse_detect_state = 0; 12000e43e99cSbellard break; 12010e43e99cSbellard case 3: 12020e43e99cSbellard if (val == 80) 12030e43e99cSbellard s->mouse_type = 4; /* IMEX */ 12040e43e99cSbellard s->mouse_detect_state = 0; 12050e43e99cSbellard break; 12060e43e99cSbellard } 12070e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 12080e43e99cSbellard s->common.write_cmd = -1; 12090e43e99cSbellard break; 12100e43e99cSbellard case AUX_SET_RES: 12110e43e99cSbellard s->mouse_resolution = val; 12120e43e99cSbellard ps2_queue(&s->common, AUX_ACK); 12130e43e99cSbellard s->common.write_cmd = -1; 12140e43e99cSbellard break; 12150e43e99cSbellard } 12160e43e99cSbellard } 12170e43e99cSbellard 1218ef74679aSDinesh Subhraveti static void ps2_common_reset(PS2State *s) 12190e43e99cSbellard { 12200e43e99cSbellard s->write_cmd = -1; 1221954ee55bSGerd Hoffmann ps2_reset_queue(s); 1222deeccef3Saliguori s->update_irq(s->update_arg, 0); 12230e43e99cSbellard } 12240e43e99cSbellard 12252858ab09SGonglei static void ps2_common_post_load(PS2State *s) 12262858ab09SGonglei { 12272858ab09SGonglei PS2Queue *q = &s->queue; 1228*802cbcb7SPrasad J Pandit uint8_t i, size; 1229*802cbcb7SPrasad J Pandit uint8_t tmp_data[PS2_QUEUE_SIZE]; 12302858ab09SGonglei 12312858ab09SGonglei /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */ 1232*802cbcb7SPrasad J Pandit size = (q->count < 0 || q->count > PS2_QUEUE_SIZE) ? 0 : q->count; 12332858ab09SGonglei 12342858ab09SGonglei /* move the queue elements to the start of data array */ 12352858ab09SGonglei for (i = 0; i < size; i++) { 1236*802cbcb7SPrasad J Pandit if (q->rptr < 0 || q->rptr >= sizeof(q->data)) { 12372858ab09SGonglei q->rptr = 0; 12382858ab09SGonglei } 1239*802cbcb7SPrasad J Pandit tmp_data[i] = q->data[q->rptr++]; 12402858ab09SGonglei } 12412858ab09SGonglei memcpy(q->data, tmp_data, size); 1242*802cbcb7SPrasad J Pandit 12432858ab09SGonglei /* reset rptr/wptr/count */ 12442858ab09SGonglei q->rptr = 0; 12452858ab09SGonglei q->wptr = size; 12462858ab09SGonglei q->count = size; 12472858ab09SGonglei s->update_irq(s->update_arg, q->count != 0); 12482858ab09SGonglei } 12492858ab09SGonglei 1250ef74679aSDinesh Subhraveti static void ps2_kbd_reset(void *opaque) 1251ef74679aSDinesh Subhraveti { 1252ef74679aSDinesh Subhraveti PS2KbdState *s = (PS2KbdState *) opaque; 1253ef74679aSDinesh Subhraveti 12545edab03dSDon Koch trace_ps2_kbd_reset(opaque); 1255ef74679aSDinesh Subhraveti ps2_common_reset(&s->common); 1256ef74679aSDinesh Subhraveti s->scan_enabled = 0; 1257ef74679aSDinesh Subhraveti s->translate = 0; 1258089adafdSHervé Poussineau s->scancode_set = 2; 1259620775d1SDaniel P. Berrange s->modifiers = 0; 1260ef74679aSDinesh Subhraveti } 1261ef74679aSDinesh Subhraveti 1262ef74679aSDinesh Subhraveti static void ps2_mouse_reset(void *opaque) 1263ef74679aSDinesh Subhraveti { 1264ef74679aSDinesh Subhraveti PS2MouseState *s = (PS2MouseState *) opaque; 1265ef74679aSDinesh Subhraveti 12665edab03dSDon Koch trace_ps2_mouse_reset(opaque); 1267ef74679aSDinesh Subhraveti ps2_common_reset(&s->common); 1268ef74679aSDinesh Subhraveti s->mouse_status = 0; 1269ef74679aSDinesh Subhraveti s->mouse_resolution = 0; 1270ef74679aSDinesh Subhraveti s->mouse_sample_rate = 0; 1271ef74679aSDinesh Subhraveti s->mouse_wrap = 0; 1272ef74679aSDinesh Subhraveti s->mouse_type = 0; 1273ef74679aSDinesh Subhraveti s->mouse_detect_state = 0; 1274ef74679aSDinesh Subhraveti s->mouse_dx = 0; 1275ef74679aSDinesh Subhraveti s->mouse_dy = 0; 1276ef74679aSDinesh Subhraveti s->mouse_dz = 0; 1277ef74679aSDinesh Subhraveti s->mouse_buttons = 0; 1278ef74679aSDinesh Subhraveti } 1279ef74679aSDinesh Subhraveti 1280b31442c3SJuan Quintela static const VMStateDescription vmstate_ps2_common = { 1281b31442c3SJuan Quintela .name = "PS2 Common State", 1282b31442c3SJuan Quintela .version_id = 3, 1283b31442c3SJuan Quintela .minimum_version_id = 2, 1284b31442c3SJuan Quintela .fields = (VMStateField[]) { 1285b31442c3SJuan Quintela VMSTATE_INT32(write_cmd, PS2State), 1286b31442c3SJuan Quintela VMSTATE_INT32(queue.rptr, PS2State), 1287b31442c3SJuan Quintela VMSTATE_INT32(queue.wptr, PS2State), 1288b31442c3SJuan Quintela VMSTATE_INT32(queue.count, PS2State), 1289b31442c3SJuan Quintela VMSTATE_BUFFER(queue.data, PS2State), 1290b31442c3SJuan Quintela VMSTATE_END_OF_LIST() 12917783e9f0Spbrook } 1292b31442c3SJuan Quintela }; 12937783e9f0Spbrook 12947f540ab5SChristophe Fergeau static bool ps2_keyboard_ledstate_needed(void *opaque) 12957f540ab5SChristophe Fergeau { 12967f540ab5SChristophe Fergeau PS2KbdState *s = opaque; 12977f540ab5SChristophe Fergeau 12987f540ab5SChristophe Fergeau return s->ledstate != 0; /* 0 is default state */ 12997f540ab5SChristophe Fergeau } 13007f540ab5SChristophe Fergeau 13017f540ab5SChristophe Fergeau static int ps2_kbd_ledstate_post_load(void *opaque, int version_id) 13027f540ab5SChristophe Fergeau { 13037f540ab5SChristophe Fergeau PS2KbdState *s = opaque; 13047f540ab5SChristophe Fergeau 13057f540ab5SChristophe Fergeau kbd_put_ledstate(s->ledstate); 13067f540ab5SChristophe Fergeau return 0; 13077f540ab5SChristophe Fergeau } 13087f540ab5SChristophe Fergeau 13097f540ab5SChristophe Fergeau static const VMStateDescription vmstate_ps2_keyboard_ledstate = { 13107f540ab5SChristophe Fergeau .name = "ps2kbd/ledstate", 13117f540ab5SChristophe Fergeau .version_id = 3, 13127f540ab5SChristophe Fergeau .minimum_version_id = 2, 13137f540ab5SChristophe Fergeau .post_load = ps2_kbd_ledstate_post_load, 13145cd8cadaSJuan Quintela .needed = ps2_keyboard_ledstate_needed, 13157f540ab5SChristophe Fergeau .fields = (VMStateField[]) { 13167f540ab5SChristophe Fergeau VMSTATE_INT32(ledstate, PS2KbdState), 13177f540ab5SChristophe Fergeau VMSTATE_END_OF_LIST() 13187f540ab5SChristophe Fergeau } 13197f540ab5SChristophe Fergeau }; 13207f540ab5SChristophe Fergeau 132157d5c005SHervé Poussineau static bool ps2_keyboard_need_high_bit_needed(void *opaque) 132257d5c005SHervé Poussineau { 132357d5c005SHervé Poussineau PS2KbdState *s = opaque; 132457d5c005SHervé Poussineau return s->need_high_bit != 0; /* 0 is the usual state */ 132557d5c005SHervé Poussineau } 132657d5c005SHervé Poussineau 132757d5c005SHervé Poussineau static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = { 132857d5c005SHervé Poussineau .name = "ps2kbd/need_high_bit", 132957d5c005SHervé Poussineau .version_id = 1, 133057d5c005SHervé Poussineau .minimum_version_id = 1, 133157d5c005SHervé Poussineau .needed = ps2_keyboard_need_high_bit_needed, 133257d5c005SHervé Poussineau .fields = (VMStateField[]) { 133357d5c005SHervé Poussineau VMSTATE_BOOL(need_high_bit, PS2KbdState), 133457d5c005SHervé Poussineau VMSTATE_END_OF_LIST() 133557d5c005SHervé Poussineau } 133657d5c005SHervé Poussineau }; 133757d5c005SHervé Poussineau 1338db596c53SJuan Quintela static int ps2_kbd_post_load(void* opaque, int version_id) 13390e43e99cSbellard { 13400e43e99cSbellard PS2KbdState *s = (PS2KbdState*)opaque; 13412858ab09SGonglei PS2State *ps2 = &s->common; 13420e43e99cSbellard 1343db596c53SJuan Quintela if (version_id == 2) 1344e7d93956Saurel32 s->scancode_set=2; 13452858ab09SGonglei 13462858ab09SGonglei ps2_common_post_load(ps2); 13472858ab09SGonglei 13480e43e99cSbellard return 0; 13490e43e99cSbellard } 13500e43e99cSbellard 135144b1ff31SDr. David Alan Gilbert static int ps2_kbd_pre_save(void *opaque) 13522858ab09SGonglei { 13532858ab09SGonglei PS2KbdState *s = (PS2KbdState *)opaque; 13542858ab09SGonglei PS2State *ps2 = &s->common; 13552858ab09SGonglei 13562858ab09SGonglei ps2_common_post_load(ps2); 135744b1ff31SDr. David Alan Gilbert 135844b1ff31SDr. David Alan Gilbert return 0; 13592858ab09SGonglei } 13602858ab09SGonglei 1361b31442c3SJuan Quintela static const VMStateDescription vmstate_ps2_keyboard = { 1362b31442c3SJuan Quintela .name = "ps2kbd", 1363b31442c3SJuan Quintela .version_id = 3, 1364db596c53SJuan Quintela .minimum_version_id = 2, 1365db596c53SJuan Quintela .post_load = ps2_kbd_post_load, 13662858ab09SGonglei .pre_save = ps2_kbd_pre_save, 1367b31442c3SJuan Quintela .fields = (VMStateField[]) { 1368b31442c3SJuan Quintela VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State), 1369b31442c3SJuan Quintela VMSTATE_INT32(scan_enabled, PS2KbdState), 1370b31442c3SJuan Quintela VMSTATE_INT32(translate, PS2KbdState), 1371b31442c3SJuan Quintela VMSTATE_INT32_V(scancode_set, PS2KbdState,3), 1372b31442c3SJuan Quintela VMSTATE_END_OF_LIST() 13737f540ab5SChristophe Fergeau }, 13745cd8cadaSJuan Quintela .subsections = (const VMStateDescription*[]) { 13755cd8cadaSJuan Quintela &vmstate_ps2_keyboard_ledstate, 137657d5c005SHervé Poussineau &vmstate_ps2_keyboard_need_high_bit, 13775cd8cadaSJuan Quintela NULL 13780e43e99cSbellard } 1379b31442c3SJuan Quintela }; 1380b31442c3SJuan Quintela 13812858ab09SGonglei static int ps2_mouse_post_load(void *opaque, int version_id) 13822858ab09SGonglei { 13832858ab09SGonglei PS2MouseState *s = (PS2MouseState *)opaque; 13842858ab09SGonglei PS2State *ps2 = &s->common; 13852858ab09SGonglei 13862858ab09SGonglei ps2_common_post_load(ps2); 13872858ab09SGonglei 13882858ab09SGonglei return 0; 13892858ab09SGonglei } 13902858ab09SGonglei 139144b1ff31SDr. David Alan Gilbert static int ps2_mouse_pre_save(void *opaque) 13922858ab09SGonglei { 13932858ab09SGonglei PS2MouseState *s = (PS2MouseState *)opaque; 13942858ab09SGonglei PS2State *ps2 = &s->common; 13952858ab09SGonglei 13962858ab09SGonglei ps2_common_post_load(ps2); 139744b1ff31SDr. David Alan Gilbert 139844b1ff31SDr. David Alan Gilbert return 0; 13992858ab09SGonglei } 14002858ab09SGonglei 1401b31442c3SJuan Quintela static const VMStateDescription vmstate_ps2_mouse = { 1402b31442c3SJuan Quintela .name = "ps2mouse", 1403b31442c3SJuan Quintela .version_id = 2, 1404b31442c3SJuan Quintela .minimum_version_id = 2, 14052858ab09SGonglei .post_load = ps2_mouse_post_load, 14062858ab09SGonglei .pre_save = ps2_mouse_pre_save, 1407b31442c3SJuan Quintela .fields = (VMStateField[]) { 1408b31442c3SJuan Quintela VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State), 1409b31442c3SJuan Quintela VMSTATE_UINT8(mouse_status, PS2MouseState), 1410b31442c3SJuan Quintela VMSTATE_UINT8(mouse_resolution, PS2MouseState), 1411b31442c3SJuan Quintela VMSTATE_UINT8(mouse_sample_rate, PS2MouseState), 1412b31442c3SJuan Quintela VMSTATE_UINT8(mouse_wrap, PS2MouseState), 1413b31442c3SJuan Quintela VMSTATE_UINT8(mouse_type, PS2MouseState), 1414b31442c3SJuan Quintela VMSTATE_UINT8(mouse_detect_state, PS2MouseState), 1415b31442c3SJuan Quintela VMSTATE_INT32(mouse_dx, PS2MouseState), 1416b31442c3SJuan Quintela VMSTATE_INT32(mouse_dy, PS2MouseState), 1417b31442c3SJuan Quintela VMSTATE_INT32(mouse_dz, PS2MouseState), 1418b31442c3SJuan Quintela VMSTATE_UINT8(mouse_buttons, PS2MouseState), 1419b31442c3SJuan Quintela VMSTATE_END_OF_LIST() 1420b31442c3SJuan Quintela } 1421b31442c3SJuan Quintela }; 14220e43e99cSbellard 142366e6536eSGerd Hoffmann static QemuInputHandler ps2_keyboard_handler = { 142466e6536eSGerd Hoffmann .name = "QEMU PS/2 Keyboard", 142566e6536eSGerd Hoffmann .mask = INPUT_EVENT_MASK_KEY, 142666e6536eSGerd Hoffmann .event = ps2_keyboard_event, 142766e6536eSGerd Hoffmann }; 142866e6536eSGerd Hoffmann 14290e43e99cSbellard void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) 14300e43e99cSbellard { 14317267c094SAnthony Liguori PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState)); 14320e43e99cSbellard 14335edab03dSDon Koch trace_ps2_kbd_init(s); 14340e43e99cSbellard s->common.update_irq = update_irq; 14350e43e99cSbellard s->common.update_arg = update_arg; 1436e7d93956Saurel32 s->scancode_set = 2; 14370be71e32SAlex Williamson vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s); 143866e6536eSGerd Hoffmann qemu_input_handler_register((DeviceState *)s, 143966e6536eSGerd Hoffmann &ps2_keyboard_handler); 1440ef74679aSDinesh Subhraveti qemu_register_reset(ps2_kbd_reset, s); 14410e43e99cSbellard return s; 14420e43e99cSbellard } 14430e43e99cSbellard 14442a766d29SGerd Hoffmann static QemuInputHandler ps2_mouse_handler = { 14452a766d29SGerd Hoffmann .name = "QEMU PS/2 Mouse", 14462a766d29SGerd Hoffmann .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, 14472a766d29SGerd Hoffmann .event = ps2_mouse_event, 14482a766d29SGerd Hoffmann .sync = ps2_mouse_sync, 14492a766d29SGerd Hoffmann }; 14502a766d29SGerd Hoffmann 14510e43e99cSbellard void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) 14520e43e99cSbellard { 14537267c094SAnthony Liguori PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState)); 14540e43e99cSbellard 14555edab03dSDon Koch trace_ps2_mouse_init(s); 14560e43e99cSbellard s->common.update_irq = update_irq; 14570e43e99cSbellard s->common.update_arg = update_arg; 14580be71e32SAlex Williamson vmstate_register(NULL, 0, &vmstate_ps2_mouse, s); 14592a766d29SGerd Hoffmann qemu_input_handler_register((DeviceState *)s, 14602a766d29SGerd Hoffmann &ps2_mouse_handler); 1461ef74679aSDinesh Subhraveti qemu_register_reset(ps2_mouse_reset, s); 14620e43e99cSbellard return s; 14630e43e99cSbellard } 1464