Subversion Repositories HelenOS

Rev

Rev 4311 | 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. #ifdef CONFIG_MAC_KBD
  49. #include <genarch/kbrd/scanc_mac.h>
  50. #endif
  51.  
  52. #include <synch/spinlock.h>
  53. #include <console/chardev.h>
  54. #include <console/console.h>
  55. #include <proc/thread.h>
  56. #include <arch.h>
  57. #include <macros.h>
  58.  
  59. #define IGNORE_CODE  0x7f
  60. #define KEY_RELEASE  0x80
  61.  
  62. #define PRESSED_SHIFT     (1 << 0)
  63. #define PRESSED_CAPSLOCK  (1 << 1)
  64. #define LOCKED_CAPSLOCK   (1 << 0)
  65.  
  66. static indev_operations_t kbrd_raw_ops = {
  67.     .poll = NULL
  68. };
  69.  
  70. /** Process release of key.
  71.  *
  72.  * @param sc Scancode of the key being released.
  73.  */
  74. static void key_released(kbrd_instance_t *instance, wchar_t sc)
  75. {
  76.     spinlock_lock(&instance->keylock);
  77.    
  78.     switch (sc) {
  79.     case SC_LSHIFT:
  80.     case SC_RSHIFT:
  81.         instance->keyflags &= ~PRESSED_SHIFT;
  82.         break;
  83.     case SC_CAPSLOCK:
  84.         instance->keyflags &= ~PRESSED_CAPSLOCK;
  85.         if (instance->lockflags & LOCKED_CAPSLOCK)
  86.             instance->lockflags &= ~LOCKED_CAPSLOCK;
  87.         else
  88.             instance->lockflags |= LOCKED_CAPSLOCK;
  89.         break;
  90.     default:
  91.         break;
  92.     }
  93.    
  94.     spinlock_unlock(&instance->keylock);
  95. }
  96.  
  97. /** Process keypress.
  98.  *
  99.  * @param sc Scancode of the key being pressed.
  100.  */
  101. static void key_pressed(kbrd_instance_t *instance, wchar_t sc)
  102. {
  103.     bool letter;
  104.     bool shift;
  105.     bool capslock;
  106.    
  107.     spinlock_lock(&instance->keylock);
  108.    
  109.     switch (sc) {
  110.     case SC_LSHIFT:
  111.     case SC_RSHIFT:
  112.         instance->keyflags |= PRESSED_SHIFT;
  113.         break;
  114.     case SC_CAPSLOCK:
  115.         instance->keyflags |= PRESSED_CAPSLOCK;
  116.         break;
  117.     case SC_SCAN_ESCAPE:
  118.         break;
  119.     default:
  120.         letter = islower(sc_primary_map[sc]);
  121.         shift = instance->keyflags & PRESSED_SHIFT;
  122.         capslock = (instance->keyflags & PRESSED_CAPSLOCK) ||
  123.             (instance->lockflags & LOCKED_CAPSLOCK);
  124.        
  125.         if ((letter) && (capslock))
  126.             shift = !shift;
  127.        
  128.         if (shift)
  129.             indev_push_character(instance->sink, sc_secondary_map[sc]);
  130.         else
  131.             indev_push_character(instance->sink, sc_primary_map[sc]);
  132.         break;
  133.     }
  134.    
  135.     spinlock_unlock(&instance->keylock);
  136. }
  137.  
  138. static void kkbrd(void *arg)
  139. {
  140.     kbrd_instance_t *instance = (kbrd_instance_t *) arg;
  141.    
  142.     while (true) {
  143.         wchar_t sc = indev_pop_character(&instance->raw);
  144.        
  145.         if (sc == IGNORE_CODE)
  146.             continue;
  147.        
  148.         if (sc & KEY_RELEASE)
  149.             key_released(instance, (sc ^ KEY_RELEASE) & 0x7f);
  150.         else
  151.             key_pressed(instance, sc & 0x7f);
  152.     }
  153. }
  154.  
  155. kbrd_instance_t *kbrd_init(void)
  156. {
  157.     kbrd_instance_t *instance
  158.         = malloc(sizeof(kbrd_instance_t), FRAME_ATOMIC);
  159.     if (instance) {
  160.         instance->thread
  161.             = thread_create(kkbrd, (void *) instance, TASK, 0, "kkbrd", false);
  162.        
  163.         if (!instance->thread) {
  164.             free(instance);
  165.             return NULL;
  166.         }
  167.        
  168.         instance->sink = NULL;
  169.         indev_initialize("kbrd", &instance->raw, &kbrd_raw_ops);
  170.        
  171.         spinlock_initialize(&instance->keylock, "instance_keylock");
  172.         instance->keyflags = 0;
  173.         instance->lockflags = 0;
  174.     }
  175.    
  176.     return instance;
  177. }
  178.  
  179. indev_t *kbrd_wire(kbrd_instance_t *instance, indev_t *sink)
  180. {
  181.     ASSERT(instance);
  182.     ASSERT(sink);
  183.    
  184.     instance->sink = sink;
  185.     thread_ready(instance->thread);
  186.    
  187.     return &instance->raw;
  188. }
  189.  
  190. /** @}
  191.  */
  192.