| 1 | /* | 
|---|
| 2 |  * tty.c - a basic tty driver | 
|---|
| 3 |  * | 
|---|
| 4 |  * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless | 
|---|
| 5 |  * Copyright (c) 2011,2012 UPMC Sorbonne Universites | 
|---|
| 6 |  * | 
|---|
| 7 |  * This file is part of ALMOS-kernel. | 
|---|
| 8 |  * | 
|---|
| 9 |  * ALMOS-kernel is free software; you can redistribute it and/or modify it | 
|---|
| 10 |  * under the terms of the GNU General Public License as published by | 
|---|
| 11 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
| 12 |  * | 
|---|
| 13 |  * ALMOS-kernel is distributed in the hope that it will be useful, but | 
|---|
| 14 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 15 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 16 |  * General Public License for more details. | 
|---|
| 17 |  * | 
|---|
| 18 |  * You should have received a copy of the GNU General Public License | 
|---|
| 19 |  * along with ALMOS-kernel; if not, write to the Free Software Foundation, | 
|---|
| 20 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
| 21 |  */ | 
|---|
| 22 |  | 
|---|
| 23 | #include <config.h> | 
|---|
| 24 | #include <system.h> | 
|---|
| 25 | #include <cpu.h> | 
|---|
| 26 | #include <chdev.h> | 
|---|
| 27 | #include <driver.h> | 
|---|
| 28 | #include <cpu-io.h> | 
|---|
| 29 | #include <kmem.h> | 
|---|
| 30 | #include <libk.h> | 
|---|
| 31 | #include <tty.h> | 
|---|
| 32 | #include <rwlock.h> | 
|---|
| 33 | #include <cpu-trace.h> | 
|---|
| 34 | #include <thread.h> | 
|---|
| 35 | #include <mwmr.h> | 
|---|
| 36 |  | 
|---|
| 37 | struct device_s ttys_tbl[TTY_DEV_NR]; | 
|---|
| 38 |  | 
|---|
| 39 | static void tty_clear(struct device_s *tty) | 
|---|
| 40 | { | 
|---|
| 41 |         register uint_t i = 0; | 
|---|
| 42 |         struct tty_context_s *ctx; | 
|---|
| 43 |         uint8_t *vga_ram; | 
|---|
| 44 |  | 
|---|
| 45 |         ctx = (struct tty_context_s*)tty->data; | 
|---|
| 46 |         vga_ram = (uint8_t*)tty->base; | 
|---|
| 47 |  | 
|---|
| 48 |         for(i = 0; i < TTY_SIZE; i+=2) | 
|---|
| 49 |         { | 
|---|
| 50 |                 vga_ram[i] = 0; | 
|---|
| 51 |                 vga_ram[i+1] = ctx->attr; | 
|---|
| 52 |         } | 
|---|
| 53 | } | 
|---|
| 54 |  | 
|---|
| 55 |  | 
|---|
| 56 | static sint_t tty_read(struct device_s *tty, dev_request_t *rq) | 
|---|
| 57 | { | 
|---|
| 58 |         struct tty_context_s *ctx;  | 
|---|
| 59 |         register size_t size; | 
|---|
| 60 |         uint_t irq_state; | 
|---|
| 61 |         register char *dst; | 
|---|
| 62 |         register size_t count; | 
|---|
| 63 |         register uint32_t eol = 0; | 
|---|
| 64 |     | 
|---|
| 65 |         cpu_trace_write(CURRENT_THREAD->local_cpu, tty_read); | 
|---|
| 66 |  | 
|---|
| 67 |         ctx = (struct tty_context_s*)tty->data; | 
|---|
| 68 |         size = 0; | 
|---|
| 69 |         count = rq->count; | 
|---|
| 70 |         dst = rq->dst; | 
|---|
| 71 |     | 
|---|
| 72 |         if(rq->flags & DEV_RQ_NOBLOCK) | 
|---|
| 73 |                 rwlock_rdlock(&ctx->rwlock); | 
|---|
| 74 |         else | 
|---|
| 75 |                 rwlock_wrlock(&ctx->rwlock); | 
|---|
| 76 |  | 
|---|
| 77 |         spinlock_lock_noirq(&tty->lock, &irq_state); | 
|---|
| 78 |  | 
|---|
| 79 |         size = mwmr_read(ctx->in_channel, dst, count); | 
|---|
| 80 |         eol = ctx->eol; | 
|---|
| 81 |     | 
|---|
| 82 |         if((eol) || (size == count) || (rq->flags & DEV_RQ_NOBLOCK)) | 
|---|
| 83 |         { | 
|---|
| 84 |                 ctx->eol = 0; | 
|---|
| 85 |                 spinlock_unlock_noirq(&tty->lock, irq_state); | 
|---|
| 86 |                 rwlock_unlock(&ctx->rwlock); | 
|---|
| 87 |                 return size; | 
|---|
| 88 |         } | 
|---|
| 89 |  | 
|---|
| 90 |         rq->count -= size; | 
|---|
| 91 |         rq->dst = dst + size; | 
|---|
| 92 |         ctx->pending_rq = rq; | 
|---|
| 93 |  | 
|---|
| 94 |         wait_on(&ctx->wait_queue, WAIT_LAST); | 
|---|
| 95 |         spinlock_unlock_noirq(&tty->lock, irq_state); | 
|---|
| 96 |         sched_sleep(CURRENT_THREAD); | 
|---|
| 97 |         rwlock_unlock(&ctx->rwlock); | 
|---|
| 98 |         return count - rq->count; | 
|---|
| 99 | } | 
|---|
| 100 |  | 
|---|
| 101 | void tty_scrollup(struct device_s *tty, int n) | 
|---|
| 102 | { | 
|---|
| 103 |         struct tty_context_s *ctx; | 
|---|
| 104 |         uint8_t *vga_ram; | 
|---|
| 105 |         uint8_t *ptr; | 
|---|
| 106 |         uint8_t *limit = (uint8_t*)((uint_t)TTY_SIZE); | 
|---|
| 107 |  | 
|---|
| 108 |         ctx = (struct tty_context_s*)tty->data; | 
|---|
| 109 |         vga_ram = (uint8_t*)tty->base; | 
|---|
| 110 |  | 
|---|
| 111 |         for(; vga_ram < limit; vga_ram+=2) | 
|---|
| 112 |         { | 
|---|
| 113 |                 ptr=&vga_ram[n*2*TTY_XSIZE]; | 
|---|
| 114 |      | 
|---|
| 115 |                 if(ptr < limit)  | 
|---|
| 116 |                 { | 
|---|
| 117 |                         *vga_ram = *ptr; | 
|---|
| 118 |                         *(vga_ram + 1) = *(ptr+1); | 
|---|
| 119 |                 } | 
|---|
| 120 |                 else | 
|---|
| 121 |                 { | 
|---|
| 122 |                         *vga_ram = 0; | 
|---|
| 123 |                         *(vga_ram+1) = 0x07; | 
|---|
| 124 |                 } | 
|---|
| 125 |         } | 
|---|
| 126 |    | 
|---|
| 127 |         ctx->pos_Y -= n; | 
|---|
| 128 |         ctx->pos_Y = (ctx->pos_Y < 0) ? 0 : ctx->pos_Y; | 
|---|
| 129 | } | 
|---|
| 130 |  | 
|---|
| 131 | static void tty_cleanup(struct device_s *tty) | 
|---|
| 132 | { | 
|---|
| 133 |         struct tty_context_s *ctx; | 
|---|
| 134 |  | 
|---|
| 135 |         ctx = (struct tty_context_s*)tty->data; | 
|---|
| 136 |         tty_clear(tty); | 
|---|
| 137 |         ctx->pos_Y = 0; | 
|---|
| 138 |         ctx->pos_X = 0; | 
|---|
| 139 | } | 
|---|
| 140 |  | 
|---|
| 141 | #define TTY_CURSOR_CMD        0x3d4 | 
|---|
| 142 | #define TTY_CURSOR_DATA       0x3d5 | 
|---|
| 143 |  | 
|---|
| 144 | void tty_move_cursor(uint_t pos_X, uint_t pos_Y) | 
|---|
| 145 | { | 
|---|
| 146 |         uint_t pos; | 
|---|
| 147 |  | 
|---|
| 148 |         pos = pos_Y * TTY_XSIZE + pos_X; | 
|---|
| 149 |         cpu_io_out8(TTY_CURSOR_CMD, 0x0f); | 
|---|
| 150 |         cpu_io_out8(TTY_CURSOR_DATA, pos); | 
|---|
| 151 |         cpu_io_out8(TTY_CURSOR_CMD, 0x0e); | 
|---|
| 152 |         cpu_io_out8(TTY_CURSOR_DATA, pos >> 8); | 
|---|
| 153 | } | 
|---|
| 154 |  | 
|---|
| 155 | static void tty_putc(struct device_s *tty, uint8_t ch) | 
|---|
| 156 | { | 
|---|
| 157 |         struct tty_context_s *ctx; | 
|---|
| 158 |         uint8_t *vga_ram; | 
|---|
| 159 |         int offset; | 
|---|
| 160 |  | 
|---|
| 161 |         ctx = (struct tty_context_s*)tty->data; | 
|---|
| 162 |         vga_ram = (uint8_t*)tty->base; | 
|---|
| 163 |  | 
|---|
| 164 |         switch (ch) | 
|---|
| 165 |         { | 
|---|
| 166 |         case '\b': | 
|---|
| 167 |                 ctx->pos_X --; | 
|---|
| 168 |                 break; | 
|---|
| 169 |         case '\t': | 
|---|
| 170 |                 ctx->pos_X += 8; | 
|---|
| 171 |                 break; | 
|---|
| 172 |  | 
|---|
| 173 |         case '\r': | 
|---|
| 174 |                 ctx->pos_X = 0; | 
|---|
| 175 |                 break; | 
|---|
| 176 |  | 
|---|
| 177 |         case '\n':       | 
|---|
| 178 |                 ctx->pos_X = 0; | 
|---|
| 179 |                 ctx->pos_Y ++; | 
|---|
| 180 |                 break; | 
|---|
| 181 |    | 
|---|
| 182 |         default: | 
|---|
| 183 |                 offset = 2*TTY_XSIZE*ctx->pos_Y + 2*ctx->pos_X; | 
|---|
| 184 |                 ctx->pos_X++; | 
|---|
| 185 |                 vga_ram[offset] = ch; | 
|---|
| 186 |                 vga_ram[offset + 1] = (uint8_t)(ctx->attr & 0xFF); | 
|---|
| 187 |         } | 
|---|
| 188 |  | 
|---|
| 189 |         if(ctx->pos_X >= TTY_XSIZE) | 
|---|
| 190 |         { | 
|---|
| 191 |                 ctx->pos_X = 0; | 
|---|
| 192 |                 ctx->pos_Y ++; | 
|---|
| 193 |         } | 
|---|
| 194 |    | 
|---|
| 195 | #if 1 | 
|---|
| 196 |         if(ctx->pos_Y >= TTY_YSIZE) | 
|---|
| 197 |         { | 
|---|
| 198 |                 tty_cleanup(tty); | 
|---|
| 199 |                 //ctx->pos_Y = 0; | 
|---|
| 200 |         } | 
|---|
| 201 | #endif | 
|---|
| 202 | } | 
|---|
| 203 |  | 
|---|
| 204 |  | 
|---|
| 205 | static sint_t tty_write(struct device_s *tty, dev_request_t *rq) | 
|---|
| 206 | { | 
|---|
| 207 |         struct tty_context_s *ctx;  | 
|---|
| 208 |         register unsigned int i; | 
|---|
| 209 |         register size_t size = rq->count; | 
|---|
| 210 |    | 
|---|
| 211 |         cpu_trace_write(CURRENT_THREAD->local_cpu, tty_write); | 
|---|
| 212 |    | 
|---|
| 213 |         ctx = (struct tty_context_s*)tty->data; | 
|---|
| 214 |    | 
|---|
| 215 |         if(!(rq->flags & DEV_RQ_NOBLOCK)) | 
|---|
| 216 |                 rwlock_wrlock(&ctx->rwlock); | 
|---|
| 217 |  | 
|---|
| 218 |         for (i = 0; i < size; i++) | 
|---|
| 219 |                 tty_putc(tty, *((uint8_t*)rq->src + i)); | 
|---|
| 220 |  | 
|---|
| 221 |         if(!(rq->flags & DEV_RQ_NOBLOCK)) | 
|---|
| 222 |                 rwlock_unlock(&ctx->rwlock); | 
|---|
| 223 |  | 
|---|
| 224 |         return size; | 
|---|
| 225 | } | 
|---|
| 226 |  | 
|---|
| 227 |  | 
|---|
| 228 | static sint_t tty_get_params(struct device_s *tty, dev_params_t *params) | 
|---|
| 229 | { | 
|---|
| 230 |         params->chr.xSize = TTY_XSIZE; | 
|---|
| 231 |         params->chr.ySize = TTY_YSIZE; | 
|---|
| 232 |         params->size = 0; | 
|---|
| 233 |         return 0; | 
|---|
| 234 | } | 
|---|
| 235 |  | 
|---|
| 236 | #define KEYBOARD_READ_REG     0x60 | 
|---|
| 237 | #define KEYBOARD_WRITE_REG    0x60 | 
|---|
| 238 | #define KEYBOARD_STATUS_REG   0x64 | 
|---|
| 239 | #define KEYBORAD_CMD_REG      0x64 | 
|---|
| 240 |  | 
|---|
| 241 | #define KEY_IS_HOLD           0x80 | 
|---|
| 242 | #define KEY_IS_LEFT_SHIFT     0x29 | 
|---|
| 243 | #define KEY_IS_RIGHT_SHIFT    0x35 | 
|---|
| 244 | #define KEY_IS_ALT            0x37 | 
|---|
| 245 | #define KEY_IS_CTRL           0x1C | 
|---|
| 246 | #define KEY_IS_CAPSLOCK       0x39 | 
|---|
| 247 |  | 
|---|
| 248 | static uint_t isLeftShift; | 
|---|
| 249 | static uint_t isRightShift; | 
|---|
| 250 | static uint_t isAlt; | 
|---|
| 251 | static uint_t isCtrl; | 
|---|
| 252 | static uint_t isCAPSLOCK; | 
|---|
| 253 |  | 
|---|
| 254 | static error_t tty_getc(struct device_s *tty) | 
|---|
| 255 | { | 
|---|
| 256 |         register uint8_t isUpper; | 
|---|
| 257 |         register uint8_t scode; | 
|---|
| 258 |         register error_t ch; | 
|---|
| 259 |         ch = -1; | 
|---|
| 260 |         scode = 0; | 
|---|
| 261 |  | 
|---|
| 262 |         /* Waite KEYBOARD OUTPUT BUFFER */ | 
|---|
| 263 |         do | 
|---|
| 264 |         { | 
|---|
| 265 |                 scode = cpu_io_in8(KEYBOARD_STATUS_REG); | 
|---|
| 266 |         }while((scode & 0x1) == 0); | 
|---|
| 267 |      | 
|---|
| 268 |         scode = cpu_io_in8(KEYBOARD_READ_REG); | 
|---|
| 269 |         scode --; | 
|---|
| 270 |    | 
|---|
| 271 |         //  isr_dmsg(DEBUG, "scode %x\n", scode); | 
|---|
| 272 |    | 
|---|
| 273 |         if(scode < KEY_IS_HOLD) | 
|---|
| 274 |         { | 
|---|
| 275 |                 switch (scode) | 
|---|
| 276 |                 { | 
|---|
| 277 |                 case KEY_IS_RIGHT_SHIFT: | 
|---|
| 278 |                         isRightShift = 1; | 
|---|
| 279 |                         break; | 
|---|
| 280 |                 case KEY_IS_CTRL: | 
|---|
| 281 |                         isCtrl = 1; | 
|---|
| 282 |                         break; | 
|---|
| 283 |                 case KEY_IS_ALT: | 
|---|
| 284 |                         isAlt = 1; | 
|---|
| 285 |                         break; | 
|---|
| 286 |                 case KEY_IS_CAPSLOCK: | 
|---|
| 287 |                         break; | 
|---|
| 288 |                 case KEY_IS_LEFT_SHIFT: | 
|---|
| 289 |                         isLeftShift = 1; | 
|---|
| 290 |                         break; | 
|---|
| 291 |                 default: | 
|---|
| 292 |                         isUpper = (isRightShift || isLeftShift || isCAPSLOCK) ? 1 : 0; | 
|---|
| 293 |                         ch = keyboard_map[(scode << 2) + isUpper + isAlt]; | 
|---|
| 294 |                 } | 
|---|
| 295 |         } | 
|---|
| 296 |         else | 
|---|
| 297 |         { | 
|---|
| 298 |                 scode -= 0x80; | 
|---|
| 299 |                 switch (scode) | 
|---|
| 300 |                 { | 
|---|
| 301 |                 case KEY_IS_RIGHT_SHIFT: | 
|---|
| 302 |                         isRightShift = 0; | 
|---|
| 303 |                         break; | 
|---|
| 304 |                 case KEY_IS_CTRL: | 
|---|
| 305 |                         isCtrl = 0; | 
|---|
| 306 |                         break; | 
|---|
| 307 |                 case KEY_IS_ALT: | 
|---|
| 308 |                         isAlt = 0; | 
|---|
| 309 |                         break; | 
|---|
| 310 |                 case KEY_IS_CAPSLOCK: | 
|---|
| 311 |                         isCAPSLOCK = (isCAPSLOCK) ? 0 : 1; | 
|---|
| 312 |                         break; | 
|---|
| 313 |                 case KEY_IS_LEFT_SHIFT: | 
|---|
| 314 |                         isLeftShift = 0; | 
|---|
| 315 |                         break; | 
|---|
| 316 |                 default: | 
|---|
| 317 |                         /* No action for other scan code */ | 
|---|
| 318 |                         break; | 
|---|
| 319 |                 } | 
|---|
| 320 |         } | 
|---|
| 321 |    | 
|---|
| 322 |         struct tty_context_s *ctx = tty->data; | 
|---|
| 323 |         tty_move_cursor(ctx->pos_X, ctx->pos_Y); | 
|---|
| 324 |         return ch; | 
|---|
| 325 | } | 
|---|
| 326 |  | 
|---|
| 327 | static void tty_irq_handler(struct irq_action_s *action) | 
|---|
| 328 | { | 
|---|
| 329 |         sint_t ch; | 
|---|
| 330 |         struct device_s *tty; | 
|---|
| 331 |         struct tty_context_s *ctx;  | 
|---|
| 332 |         register char *dst; | 
|---|
| 333 |         volatile uint32_t *base; | 
|---|
| 334 |     | 
|---|
| 335 |         cpu_trace_write(CURRENT_THREAD->local_cpu, tty_irq_handler); | 
|---|
| 336 |  | 
|---|
| 337 |         tty = action->dev; | 
|---|
| 338 |         base = tty->base; | 
|---|
| 339 |         ctx = (struct tty_context_s*)tty->data; | 
|---|
| 340 |  | 
|---|
| 341 |         if((ch = tty_getc(tty)) & 0x80) | 
|---|
| 342 |                 return; | 
|---|
| 343 |  | 
|---|
| 344 |         cpu_spinlock_lock(&tty->lock.val); | 
|---|
| 345 |  | 
|---|
| 346 |         if(ctx->pending_rq != NULL) | 
|---|
| 347 |         { | 
|---|
| 348 |                 dst = ctx->pending_rq->dst; | 
|---|
| 349 |                 *(dst ++) = ch; | 
|---|
| 350 |                 ctx->pending_rq->dst = dst; | 
|---|
| 351 |                 ctx->pending_rq->count --; | 
|---|
| 352 |  | 
|---|
| 353 |                 if((ch == '\n') || (ctx->pending_rq->count == 0)) | 
|---|
| 354 |                 { | 
|---|
| 355 |                         wakeup_one(&ctx->wait_queue, WAIT_FIRST); | 
|---|
| 356 |                         ctx->pending_rq = NULL; | 
|---|
| 357 |                 } | 
|---|
| 358 |         } | 
|---|
| 359 |         else | 
|---|
| 360 |         { | 
|---|
| 361 |                 mwmr_write(ctx->in_channel, &ch, 1); | 
|---|
| 362 |                 if(ch == '\n') ctx->eol = 1; | 
|---|
| 363 |         } | 
|---|
| 364 |  | 
|---|
| 365 | #if CONFIG_TTY_ECHO_MODE | 
|---|
| 366 |         switch(ch) | 
|---|
| 367 |         { | 
|---|
| 368 |         case '\b': | 
|---|
| 369 |         case 0x7F: | 
|---|
| 370 |                 tty_putc(tty, '\b'); | 
|---|
| 371 |         tty_putc(tty, ' '); | 
|---|
| 372 |         tty_putc(tty, '\b'); | 
|---|
| 373 |         break; | 
|---|
| 374 |         default: | 
|---|
| 375 |                 tty_putc(tty, ch); | 
|---|
| 376 |         } | 
|---|
| 377 | #endif | 
|---|
| 378 |  | 
|---|
| 379 |         cpu_spinlock_unlock(&tty->lock.val); | 
|---|
| 380 | } | 
|---|
| 381 |  | 
|---|
| 382 | void ibmpc_tty_init(struct device_s *tty, void *base, uint_t irq, uint_t tty_id) | 
|---|
| 383 | { | 
|---|
| 384 |         struct tty_context_s *ctx; | 
|---|
| 385 |    | 
|---|
| 386 |         isRightShift = 0; | 
|---|
| 387 |         isLeftShift = 0; | 
|---|
| 388 |         isCtrl = 0; | 
|---|
| 389 |         isAlt = 0; | 
|---|
| 390 |         isCAPSLOCK = 0; | 
|---|
| 391 |  | 
|---|
| 392 |         spinlock_init(&tty->lock); | 
|---|
| 393 |         tty->base = base; | 
|---|
| 394 |         tty->irq = irq; | 
|---|
| 395 |         tty->type = DEV_CHR; | 
|---|
| 396 |  | 
|---|
| 397 |         tty->action.dev = tty; | 
|---|
| 398 |         tty->action.irq_handler = &tty_irq_handler; | 
|---|
| 399 |         tty->action.data = NULL; | 
|---|
| 400 |   | 
|---|
| 401 |         tty->op.dev.open = NULL; | 
|---|
| 402 |         tty->op.dev.read = &tty_read; | 
|---|
| 403 |         tty->op.dev.write = &tty_write; | 
|---|
| 404 |         tty->op.dev.close = NULL; | 
|---|
| 405 |         tty->op.dev.lseek = NULL; | 
|---|
| 406 |         tty->op.dev.set_params = NULL; | 
|---|
| 407 |         tty->op.dev.get_params = &tty_get_params; | 
|---|
| 408 |  | 
|---|
| 409 |         ctx = kbootMem_calloc(sizeof(*ctx)); | 
|---|
| 410 |         ctx->id = tty_id; | 
|---|
| 411 |         ctx->in_channel = mwmr_init(1,TTY_BUFFER_DEPTH, 0); | 
|---|
| 412 |         rwlock_init(&ctx->rwlock); | 
|---|
| 413 |         ctx->eol = 0; | 
|---|
| 414 |         ctx->attr = 0x07; | 
|---|
| 415 |         tty->data = (void*) ctx; | 
|---|
| 416 |         sprintk(tty->name, "TTY%d", tty_id); | 
|---|
| 417 |         metafs_init(&tty->node, tty->name); | 
|---|
| 418 |         wait_queue_init(&ctx->wait_queue,tty->name); | 
|---|
| 419 |         tty_clear(tty); | 
|---|
| 420 | } | 
|---|
| 421 |  | 
|---|
| 422 |  | 
|---|
| 423 | uint8_t keyboard_map[] = { 0x1B, 0x1B, 0x1B, 0x1B, | 
|---|
| 424 |                            '&', '1', '1', '1', | 
|---|
| 425 |                            '~', '2', '2', '2', | 
|---|
| 426 |                            '"', '3', '3', '3', | 
|---|
| 427 |                            '\'','4', '{', '{', | 
|---|
| 428 |                            '(', '5', '5', '5', | 
|---|
| 429 |                            '-', '6', '|', '|', | 
|---|
| 430 |                            '`', '7', '7', '7', | 
|---|
| 431 |                            '_', '8', '\\', '\\', | 
|---|
| 432 |                            '^', '9', '9', '9', | 
|---|
| 433 |                            '@', '0', '0', '0', | 
|---|
| 434 |                            ')', ']', '-', '-', | 
|---|
| 435 |                            '=', '+', '}','}', | 
|---|
| 436 |                            '\b','\b', 0x7F,'\b', | 
|---|
| 437 |                            '\t','\t','\t','\t', | 
|---|
| 438 |                            'a', 'A', 'a', 'a', | 
|---|
| 439 |                            'z', 'Z', 'z', 'z', | 
|---|
| 440 |                            'e', 'E', 'e', 'e', | 
|---|
| 441 |                            'r', 'R', 'r', 'r', | 
|---|
| 442 |                            't', 'T', 't', 't', | 
|---|
| 443 |                            'y', 'Y', 'y', 'y', | 
|---|
| 444 |                            'u', 'U', 'u', 'u', | 
|---|
| 445 |                            'i', 'I', 'i', 'i', | 
|---|
| 446 |                            'o', 'O', 'o', 'o', | 
|---|
| 447 |                            'p', 'P', 'p', 'p', | 
|---|
| 448 |                            '[', '{', '[', '[', | 
|---|
| 449 |                            '$', '$', '$', ']', | 
|---|
| 450 |                            '\n','\n','\n','\n', | 
|---|
| 451 |                            0xFF, 0xFF, 0xFF, 0xFF, | 
|---|
| 452 |                            'q', 'A', 'a', 'a', | 
|---|
| 453 |                            's', 'S', 's', 's', | 
|---|
| 454 |                            'd', 'D', 'd', 'd', | 
|---|
| 455 |                            'f', 'F', 'f', 'f', | 
|---|
| 456 |                            'g', 'G', 'g', 'g', | 
|---|
| 457 |                            'h', 'H', 'h', 'h', | 
|---|
| 458 |                            'j', 'J', 'j', 'j', | 
|---|
| 459 |                            'k', 'K', 'k', 'k', | 
|---|
| 460 |                            'l', 'L', 'l', 'l', | 
|---|
| 461 |                            'm', 'M', ';', ';', | 
|---|
| 462 |                            '%', '%', '%', '%', | 
|---|
| 463 |                            0x28, 0x28, 0x28, 0x28, | 
|---|
| 464 |                            0x29, 0x29, 0x29, 0x29, /* Left Shift (41) */ | 
|---|
| 465 |                            '*', '*', '*', '*', | 
|---|
| 466 |                            'w', 'W', 'w', 'w', | 
|---|
| 467 |                            'x', 'X', 'x', 'x', | 
|---|
| 468 |                            'c', 'C', 'c', 'c', | 
|---|
| 469 |                            'v', 'V', 'v', 'v', | 
|---|
| 470 |                            'b', 'B', 'b', 'b', | 
|---|
| 471 |                            'n', 'N', 'n', 'n', | 
|---|
| 472 |                            ',', '?', ',', ',', | 
|---|
| 473 |                            ';', '.', ';', ';', | 
|---|
| 474 |                            ':', '/', ':', ':', | 
|---|
| 475 |                            '!', '!', '!', '!', | 
|---|
| 476 |                            0x35, 0x35, 0x35, 0x35,      /*      Rshift  (0x35)  */ | 
|---|
| 477 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 478 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 479 |                            ' ', ' ', ' ', ' ',          /*      space   */ | 
|---|
| 480 |                            0x39, 0x39, 0x39, 0x39,       | 
|---|
| 481 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 482 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 483 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 484 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 485 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 486 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 487 |                            0xFF, 0xFF, 0xFF, 0xFF, /* 0x40 */    | 
|---|
| 488 |                            0xFF, 0xFF, 0xFF, 0xFF,  | 
|---|
| 489 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 490 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 491 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 492 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 493 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 494 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 495 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 496 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 497 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 498 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 499 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 500 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 501 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 502 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 503 |                            0xFF, 0xFF, 0xFF, 0xFF, /* 0x50 */ | 
|---|
| 504 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 505 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 506 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 507 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 508 |                            '<', '>', '<', '<', | 
|---|
| 509 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 510 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 511 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 512 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 513 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 514 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 515 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 516 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 517 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 518 |                            0xFF, 0xFF, 0xFF, 0xFF,       | 
|---|
| 519 |                            0xFF, 0xFF, 0xFF, 0xFF, /* 0x60 */ | 
|---|
| 520 |                            0xFF, 0xFF, 0xFF, 0xFF}; | 
|---|