1/* 2 * Copyright (c) 2011, 2018 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Ali Saidi 38 */ 39 40#include "dev/ps2/types.hh" 41 42#include <list> 43 44#include "base/logging.hh" 45#include "x11keysym/keysym.h" 46 47const std::vector<uint8_t> Ps2::Keyboard::ID{0xAB, 0x83}; 48const std::vector<uint8_t> Ps2::Mouse::ID{0x00}; 49 50namespace Ps2 { 51 52/** Table to convert simple key symbols (0x00XX) into ps2 bytes. Lower byte 53 * is the scan code to send and upper byte is if a modifier is required to 54 * generate it. The table generates us keyboard codes, (e.g. the guest is 55 * supposed to recognize the keyboard as en_US). A new table would be required 56 * for another locale. 57 */ 58 59static const uint16_t keySymToPs2Byte[128] = { 60// 0 / 8 1 / 9 2 / A 3 / B 4 / C 5 / D 6 / E 7 / F 61 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00-0x07 62 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x08-0x0f 63 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x10-0x17 64 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x18-0x1f 65 0x0029, 0x0116, 0x0152, 0x0126, 0x0125, 0x012e, 0x013d, 0x0052, // 0x20-0x27 66 0x0146, 0x0145, 0x013e, 0x0155, 0x0041, 0x004e, 0x0049, 0x004a, // 0x28-0x2f 67 0x0045, 0x0016, 0x001e, 0x0026, 0x0025, 0x002e, 0x0036, 0x003d, // 0x30-0x37 68 0x003e, 0x0046, 0x014c, 0x004c, 0x0141, 0x0055, 0x0149, 0x014a, // 0x38-0x3f 69 0x011e, 0x011c, 0x0132, 0x0121, 0x0123, 0x0124, 0x012b, 0x0134, // 0x40-0x47 70 0x0133, 0x0143, 0x013b, 0x0142, 0x014b, 0x013a, 0x0131, 0x0144, // 0x48-0x4f 71 0x014d, 0x0115, 0x012d, 0x011b, 0x012c, 0x013c, 0x012a, 0x011d, // 0x50-0x57 72 0x0122, 0x0135, 0x011a, 0x0054, 0x005d, 0x005b, 0x0136, 0x014e, // 0x58-0x5f 73 0x000e, 0x001c, 0x0032, 0x0021, 0x0023, 0x0024, 0x002b, 0x0034, // 0x60-0x67 74 0x0033, 0x0043, 0x003b, 0x0042, 0x004b, 0x003a, 0x0031, 0x0044, // 0x68-0x6f 75 0x004d, 0x0015, 0x002d, 0x001b, 0x002c, 0x003c, 0x002a, 0x001d, // 0x70-0x77 76 0x0022, 0x0035, 0x001a, 0x0154, 0x015d, 0x015b, 0x010e, 0x0000 // 0x78-0x7f 77}; 78 79const uint8_t ShiftKey = 0x12; 80const uint8_t BreakKey = 0xf0; 81const uint8_t ExtendedKey = 0xe0; 82const uint32_t UpperKeys = 0xff00; 83 84void 85keySymToPs2(uint32_t key, bool down, bool &cur_shift, 86 std::list<uint8_t> &keys) 87{ 88 if (key <= XK_asciitilde) { 89 uint16_t tmp = keySymToPs2Byte[key]; 90 uint8_t code = tmp & 0xff; 91 bool shift = tmp >> 8; 92 93 if (down) { 94 if (!cur_shift && shift) { 95 keys.push_back(ShiftKey); 96 cur_shift = true; 97 } 98 keys.push_back(code); 99 } else { 100 if (cur_shift && !shift) { 101 keys.push_back(BreakKey); 102 keys.push_back(ShiftKey); 103 cur_shift = false; 104 } 105 keys.push_back(BreakKey); 106 keys.push_back(code); 107 } 108 } else { 109 if ((key & UpperKeys) == UpperKeys) { 110 bool extended = false; 111 switch (key) { 112 case XK_BackSpace: 113 keys.push_back(0x66); 114 break; 115 case XK_Tab: 116 keys.push_back(0x0d); 117 break; 118 case XK_Return: 119 keys.push_back(0x5a); 120 break; 121 case XK_Escape: 122 keys.push_back(0x76); 123 break; 124 case XK_Delete: 125 extended = true; 126 keys.push_back(0x71); 127 break; 128 case XK_Home: 129 extended = true; 130 keys.push_back(0x6c); 131 break; 132 case XK_Left: 133 extended = true; 134 keys.push_back(0x6b); 135 break; 136 case XK_Right: 137 extended = true; 138 keys.push_back(0x74); 139 break; 140 case XK_Down: 141 extended = true; 142 keys.push_back(0x72); 143 break; 144 case XK_Up: 145 extended = true; 146 keys.push_back(0x75); 147 break; 148 case XK_Page_Up: 149 extended = true; 150 keys.push_back(0x7d); 151 break; 152 case XK_Page_Down: 153 extended = true; 154 keys.push_back(0x7a); 155 break; 156 case XK_End: 157 extended = true; 158 keys.push_back(0x69); 159 break; 160 case XK_Shift_L: 161 keys.push_back(0x12); 162 if (down) 163 cur_shift = true; 164 else 165 cur_shift = false; 166 break; 167 case XK_Shift_R: 168 keys.push_back(0x59); 169 if (down) 170 cur_shift = true; 171 else 172 cur_shift = false; 173 break; 174 case XK_Control_L: 175 keys.push_back(0x14); 176 break; 177 case XK_Control_R: 178 extended = true; 179 keys.push_back(0x14); 180 break; 181 case XK_Alt_L: 182 keys.push_back(0x11); 183 break; 184 case XK_Alt_R: 185 extended = true; 186 keys.push_back(0x11); 187 break; 188 default: 189 warn("Unknown extended key %#x\n", key); 190 return; 191 } 192 193 if (extended) { 194 if (down) { 195 keys.push_front(ExtendedKey); 196 } else { 197 keys.push_front(BreakKey); 198 keys.push_front(ExtendedKey); 199 } 200 } else { 201 if (!down) 202 keys.push_front(BreakKey); 203 } 204 } // upper keys 205 } // extended keys 206 return; 207} 208 209} /* namespace Ps2 */ 210 211