/ adafruit_hid / keyboard_layout_us.py
keyboard_layout_us.py
1 # The MIT License (MIT) 2 # 3 # Copyright (c) 2017 Dan Halbert 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy 6 # of this software and associated documentation files (the "Software"), to deal 7 # in the Software without restriction, including without limitation the rights 8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 # copies of the Software, and to permit persons to whom the Software is 10 # furnished to do so, subject to the following conditions: 11 # 12 # The above copyright notice and this permission notice shall be included in 13 # all copies or substantial portions of the Software. 14 # 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 # THE SOFTWARE. 22 # 23 24 """ 25 `adafruit_hid.keyboard_layout_us.KeyboardLayoutUS` 26 ======================================================= 27 28 * Author(s): Dan Halbert 29 """ 30 31 from .keycode import Keycode 32 33 34 class KeyboardLayoutUS: 35 """Map ASCII characters to appropriate keypresses on a standard US PC keyboard. 36 37 Non-ASCII characters and most control characters will raise an exception. 38 """ 39 40 # The ASCII_TO_KEYCODE bytes object is used as a table to maps ASCII 0-127 41 # to the corresponding # keycode on a US 104-key keyboard. 42 # The user should not normally need to use this table, 43 # but it is not marked as private. 44 # 45 # Because the table only goes to 127, we use the top bit of each byte (ox80) to indicate 46 # that the shift key should be pressed. So any values 0x{8,9,a,b}* are shifted characters. 47 # 48 # The Python compiler will concatenate all these bytes literals into a single bytes object. 49 # Micropython/CircuitPython will store the resulting bytes constant in flash memory 50 # if it's in a .mpy file, so it doesn't use up valuable RAM. 51 # 52 # \x00 entries have no keyboard key and so won't be sent. 53 SHIFT_FLAG = 0x80 54 ASCII_TO_KEYCODE = ( 55 b"\x00" # NUL 56 b"\x00" # SOH 57 b"\x00" # STX 58 b"\x00" # ETX 59 b"\x00" # EOT 60 b"\x00" # ENQ 61 b"\x00" # ACK 62 b"\x00" # BEL \a 63 b"\x2a" # BS BACKSPACE \b (called DELETE in the usb.org document) 64 b"\x2b" # TAB \t 65 b"\x28" # LF \n (called Return or ENTER in the usb.org document) 66 b"\x00" # VT \v 67 b"\x00" # FF \f 68 b"\x00" # CR \r 69 b"\x00" # SO 70 b"\x00" # SI 71 b"\x00" # DLE 72 b"\x00" # DC1 73 b"\x00" # DC2 74 b"\x00" # DC3 75 b"\x00" # DC4 76 b"\x00" # NAK 77 b"\x00" # SYN 78 b"\x00" # ETB 79 b"\x00" # CAN 80 b"\x00" # EM 81 b"\x00" # SUB 82 b"\x29" # ESC 83 b"\x00" # FS 84 b"\x00" # GS 85 b"\x00" # RS 86 b"\x00" # US 87 b"\x2c" # SPACE 88 b"\x9e" # ! x1e|SHIFT_FLAG (shift 1) 89 b"\xb4" # " x34|SHIFT_FLAG (shift ') 90 b"\xa0" # # x20|SHIFT_FLAG (shift 3) 91 b"\xa1" # $ x21|SHIFT_FLAG (shift 4) 92 b"\xa2" # % x22|SHIFT_FLAG (shift 5) 93 b"\xa4" # & x24|SHIFT_FLAG (shift 7) 94 b"\x34" # ' 95 b"\xa6" # ( x26|SHIFT_FLAG (shift 9) 96 b"\xa7" # ) x27|SHIFT_FLAG (shift 0) 97 b"\xa5" # * x25|SHIFT_FLAG (shift 8) 98 b"\xae" # + x2e|SHIFT_FLAG (shift =) 99 b"\x36" # , 100 b"\x2d" # - 101 b"\x37" # . 102 b"\x38" # / 103 b"\x27" # 0 104 b"\x1e" # 1 105 b"\x1f" # 2 106 b"\x20" # 3 107 b"\x21" # 4 108 b"\x22" # 5 109 b"\x23" # 6 110 b"\x24" # 7 111 b"\x25" # 8 112 b"\x26" # 9 113 b"\xb3" # : x33|SHIFT_FLAG (shift ;) 114 b"\x33" # ; 115 b"\xb6" # < x36|SHIFT_FLAG (shift ,) 116 b"\x2e" # = 117 b"\xb7" # > x37|SHIFT_FLAG (shift .) 118 b"\xb8" # ? x38|SHIFT_FLAG (shift /) 119 b"\x9f" # @ x1f|SHIFT_FLAG (shift 2) 120 b"\x84" # A x04|SHIFT_FLAG (shift a) 121 b"\x85" # B x05|SHIFT_FLAG (etc.) 122 b"\x86" # C x06|SHIFT_FLAG 123 b"\x87" # D x07|SHIFT_FLAG 124 b"\x88" # E x08|SHIFT_FLAG 125 b"\x89" # F x09|SHIFT_FLAG 126 b"\x8a" # G x0a|SHIFT_FLAG 127 b"\x8b" # H x0b|SHIFT_FLAG 128 b"\x8c" # I x0c|SHIFT_FLAG 129 b"\x8d" # J x0d|SHIFT_FLAG 130 b"\x8e" # K x0e|SHIFT_FLAG 131 b"\x8f" # L x0f|SHIFT_FLAG 132 b"\x90" # M x10|SHIFT_FLAG 133 b"\x91" # N x11|SHIFT_FLAG 134 b"\x92" # O x12|SHIFT_FLAG 135 b"\x93" # P x13|SHIFT_FLAG 136 b"\x94" # Q x14|SHIFT_FLAG 137 b"\x95" # R x15|SHIFT_FLAG 138 b"\x96" # S x16|SHIFT_FLAG 139 b"\x97" # T x17|SHIFT_FLAG 140 b"\x98" # U x18|SHIFT_FLAG 141 b"\x99" # V x19|SHIFT_FLAG 142 b"\x9a" # W x1a|SHIFT_FLAG 143 b"\x9b" # X x1b|SHIFT_FLAG 144 b"\x9c" # Y x1c|SHIFT_FLAG 145 b"\x9d" # Z x1d|SHIFT_FLAG 146 b"\x2f" # [ 147 b"\x31" # \ backslash 148 b"\x30" # ] 149 b"\xa3" # ^ x23|SHIFT_FLAG (shift 6) 150 b"\xad" # _ x2d|SHIFT_FLAG (shift -) 151 b"\x35" # ` 152 b"\x04" # a 153 b"\x05" # b 154 b"\x06" # c 155 b"\x07" # d 156 b"\x08" # e 157 b"\x09" # f 158 b"\x0a" # g 159 b"\x0b" # h 160 b"\x0c" # i 161 b"\x0d" # j 162 b"\x0e" # k 163 b"\x0f" # l 164 b"\x10" # m 165 b"\x11" # n 166 b"\x12" # o 167 b"\x13" # p 168 b"\x14" # q 169 b"\x15" # r 170 b"\x16" # s 171 b"\x17" # t 172 b"\x18" # u 173 b"\x19" # v 174 b"\x1a" # w 175 b"\x1b" # x 176 b"\x1c" # y 177 b"\x1d" # z 178 b"\xaf" # { x2f|SHIFT_FLAG (shift [) 179 b"\xb1" # | x31|SHIFT_FLAG (shift \) 180 b"\xb0" # } x30|SHIFT_FLAG (shift ]) 181 b"\xb5" # ~ x35|SHIFT_FLAG (shift `) 182 b"\x4c" # DEL DELETE (called Forward Delete in usb.org document) 183 ) 184 185 def __init__(self, keyboard): 186 """Specify the layout for the given keyboard. 187 188 :param keyboard: a Keyboard object. Write characters to this keyboard when requested. 189 190 Example:: 191 192 kbd = Keyboard(usb_hid.devices) 193 layout = KeyboardLayoutUS(kbd) 194 """ 195 196 self.keyboard = keyboard 197 198 def write(self, string): 199 """Type the string by pressing and releasing keys on my keyboard. 200 201 :param string: A string of ASCII characters. 202 :raises ValueError: if any of the characters are not ASCII or have no keycode 203 (such as some control characters). 204 205 Example:: 206 207 # Write abc followed by Enter to the keyboard 208 layout.write('abc\\n') 209 """ 210 for char in string: 211 keycode = self._char_to_keycode(char) 212 # If this is a shifted char, clear the SHIFT flag and press the SHIFT key. 213 if keycode & self.SHIFT_FLAG: 214 keycode &= ~self.SHIFT_FLAG 215 self.keyboard.press(Keycode.SHIFT) 216 self.keyboard.press(keycode) 217 self.keyboard.release_all() 218 219 def keycodes(self, char): 220 """Return a tuple of keycodes needed to type the given character. 221 222 :param char: A single ASCII character in a string. 223 :type char: str of length one. 224 :returns: tuple of Keycode keycodes. 225 :raises ValueError: if ``char`` is not ASCII or there is no keycode for it. 226 227 Examples:: 228 229 # Returns (Keycode.TAB,) 230 keycodes('\t') 231 # Returns (Keycode.A,) 232 keycode('a') 233 # Returns (Keycode.SHIFT, Keycode.A) 234 keycode('A') 235 # Raises ValueError because it's a accented e and is not ASCII 236 keycode('é') 237 """ 238 keycode = self._char_to_keycode(char) 239 if keycode & self.SHIFT_FLAG: 240 return (Keycode.SHIFT, keycode & ~self.SHIFT_FLAG) 241 242 return (keycode,) 243 244 def _char_to_keycode(self, char): 245 """Return the HID keycode for the given ASCII character, with the SHIFT_FLAG possibly set. 246 247 If the character requires pressing the Shift key, the SHIFT_FLAG bit is set. 248 You must clear this bit before passing the keycode in a USB report. 249 """ 250 char_val = ord(char) 251 if char_val > 128: 252 raise ValueError("Not an ASCII character.") 253 keycode = self.ASCII_TO_KEYCODE[char_val] 254 if keycode == 0: 255 raise ValueError("No keycode available for character.") 256 return keycode