Subversion Repositories HelenOS

Rev

Rev 4042 | Rev 4296 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup genarch
  30.  * @{
  31.  */
  32. /**
  33.  * @file
  34.  * @brief   Keyboard processing.
  35.  */
  36.  
  37. #include <genarch/kbrd/kbrd.h>
  38. #include <genarch/kbrd/scanc.h>
  39.  
  40. #ifdef CONFIG_PC_KBD
  41. #include <genarch/kbrd/scanc_pc.h>
  42. #endif
  43.  
  44. #ifdef CONFIG_SUN_KBD
  45. #include <genarch/kbrd/scanc_sun.h>
  46. #endif
  47.  
  48. #include <synch/spinlock.h>
  49. #include <console/chardev.h>
  50. #include <console/console.h>
  51. #include <proc/thread.h>
  52. #include <arch.h>
  53. #include <macros.h>
  54.  
  55. #ifdef CONFIG_SUN_KBD
  56. #   define IGNORE_CODE  0x7f
  57. #endif
  58.  
  59. #define KEY_RELEASE     0x80
  60.  
  61. #define PRESSED_SHIFT       (1 << 0)
  62. #define PRESSED_CAPSLOCK    (1 << 1)
  63. #define LOCKED_CAPSLOCK     (1 << 0)
  64.  
  65. chardev_t kbrdin;
  66. static chardev_t *kbdout;
  67.  
  68. static void kbrdin_suspend(chardev_t *d)
  69. {
  70. }
  71.  
  72. static void kbrdin_resume(chardev_t *d)
  73. {
  74. }
  75.  
  76. chardev_operations_t kbrdin_ops = {
  77.     .suspend = kbrdin_suspend,
  78.     .resume = kbrdin_resume,
  79. };
  80.  
  81. SPINLOCK_INITIALIZE(keylock);       /**< keylock protects keyflags and lockflags. */
  82. static volatile int keyflags;       /**< Tracking of multiple keypresses. */
  83. static volatile int lockflags;      /**< Tracking of multiple keys lockings. */
  84.  
  85. static void key_released(uint8_t);
  86. static void key_pressed(uint8_t);
  87.  
  88. static void kkbrd(void *arg)
  89. {
  90.     chardev_t *in = (chardev_t *) arg;
  91.     uint8_t sc;
  92.  
  93.     while (1) {
  94.         sc = _getc(in);
  95.  
  96. #ifdef CONFIG_SUN_KBD
  97.         if (sc == IGNORE_CODE)
  98.             continue;
  99. #endif
  100.        
  101.         if (sc & KEY_RELEASE)
  102.             key_released(sc ^ KEY_RELEASE);
  103.         else
  104.             key_pressed(sc);
  105.     }
  106. }
  107.  
  108.  
  109. void kbrd_init(chardev_t *devout)
  110. {
  111.     thread_t *t;
  112.  
  113.     chardev_initialize("kbrd", &kbrdin, &kbrdin_ops);
  114.     kbdout = devout;
  115.    
  116.     t = thread_create(kkbrd, &kbrdin, TASK, 0, "kkbrd", false);
  117.     ASSERT(t);
  118.     thread_ready(t);
  119. }
  120.  
  121. /** Process release of key.
  122.  *
  123.  * @param sc Scancode of the key being released.
  124.  */
  125. void key_released(uint8_t sc)
  126. {
  127.     spinlock_lock(&keylock);
  128.     switch (sc) {
  129.     case SC_LSHIFT:
  130.     case SC_RSHIFT:
  131.         keyflags &= ~PRESSED_SHIFT;
  132.         break;
  133.     case SC_CAPSLOCK:
  134.         keyflags &= ~PRESSED_CAPSLOCK;
  135.         if (lockflags & LOCKED_CAPSLOCK)
  136.             lockflags &= ~LOCKED_CAPSLOCK;
  137.         else
  138.             lockflags |= LOCKED_CAPSLOCK;
  139.         break;
  140.     default:
  141.         break;
  142.     }
  143.     spinlock_unlock(&keylock);
  144. }
  145.  
  146. /** Process keypress.
  147.  *
  148.  * @param sc Scancode of the key being pressed.
  149.  */
  150. void key_pressed(uint8_t sc)
  151. {
  152.     char *map = sc_primary_map;
  153.     char ascii = sc_primary_map[sc];
  154.     bool shift, capslock;
  155.     bool letter = false;
  156.  
  157.     spinlock_lock(&keylock);
  158.     switch (sc) {
  159.     case SC_LSHIFT:
  160.     case SC_RSHIFT:
  161.             keyflags |= PRESSED_SHIFT;
  162.         break;
  163.     case SC_CAPSLOCK:
  164.         keyflags |= PRESSED_CAPSLOCK;
  165.         break;
  166.     case SC_SPEC_ESCAPE:
  167.         break;
  168.     case SC_LEFTARR:
  169.         chardev_push_character(kbdout, 0x1b);
  170.         chardev_push_character(kbdout, 0x5b);
  171.         chardev_push_character(kbdout, 0x44);
  172.         break;
  173.     case SC_RIGHTARR:
  174.         chardev_push_character(kbdout, 0x1b);
  175.         chardev_push_character(kbdout, 0x5b);
  176.         chardev_push_character(kbdout, 0x43);
  177.         break;
  178.     case SC_UPARR:
  179.         chardev_push_character(kbdout, 0x1b);
  180.         chardev_push_character(kbdout, 0x5b);
  181.         chardev_push_character(kbdout, 0x41);
  182.         break;
  183.     case SC_DOWNARR:
  184.         chardev_push_character(kbdout, 0x1b);
  185.         chardev_push_character(kbdout, 0x5b);
  186.         chardev_push_character(kbdout, 0x42);
  187.         break;
  188.     case SC_HOME:
  189.         chardev_push_character(kbdout, 0x1b);
  190.         chardev_push_character(kbdout, 0x4f);
  191.         chardev_push_character(kbdout, 0x48);
  192.         break;
  193.     case SC_END:
  194.         chardev_push_character(kbdout, 0x1b);
  195.         chardev_push_character(kbdout, 0x4f);
  196.         chardev_push_character(kbdout, 0x46);
  197.         break;
  198.     case SC_DELETE:
  199.         chardev_push_character(kbdout, 0x1b);
  200.         chardev_push_character(kbdout, 0x5b);
  201.         chardev_push_character(kbdout, 0x33);
  202.         chardev_push_character(kbdout, 0x7e);
  203.         break;
  204.     default:
  205.             letter = islower(ascii);
  206.         capslock = (keyflags & PRESSED_CAPSLOCK) ||
  207.             (lockflags & LOCKED_CAPSLOCK);
  208.         shift = keyflags & PRESSED_SHIFT;
  209.         if (letter && capslock)
  210.             shift = !shift;
  211.         if (shift)
  212.             map = sc_secondary_map;
  213.         chardev_push_character(kbdout, map[sc]);
  214.         break;
  215.     }
  216.     spinlock_unlock(&keylock);
  217. }
  218.  
  219. /** @}
  220.  */
  221.