Subversion Repositories HelenOS

Rev

Rev 4669 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Vineeth Pillai
  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 pl050 Keyboard processing.
  35.  */
  36.  
  37. #include <genarch/kbrd/kbrd.h>
  38. #include <genarch/kbrd/scanc.h>
  39.  
  40. #include <genarch/kbrd/scanc_pl050.h>
  41.  
  42. #include <synch/spinlock.h>
  43. #include <console/chardev.h>
  44. #include <console/console.h>
  45. #include <proc/thread.h>
  46. #include <arch.h>
  47. #include <macros.h>
  48.  
  49. #define PRESSED_SHIFT     (1 << 0)
  50. #define PRESSED_CAPSLOCK  (1 << 1)
  51. #define LOCKED_CAPSLOCK   (1 << 0)
  52.  
  53. #define PL050_KEY_RELEASE 0xF0
  54. #define PL050_ESC_KEY   0xE0
  55. #define PL050_CAPS_SCAN_CODE   0x58
  56. #define PL050_NUM_SCAN_CODE   0x77
  57. #define PL050_SCROLL_SCAN_CODE   0x7E
  58.  
  59. static bool is_lock_key(wchar_t);
  60.  
  61. static indev_operations_t kbrd_raw_ops = {
  62.     .poll = NULL
  63. };
  64.  
  65. /** Process release of key.
  66.  *
  67.  * @param sc Scancode of the key being released.
  68.  */
  69. static void key_released(kbrd_instance_t *instance, wchar_t sc)
  70. {
  71.     spinlock_lock(&instance->keylock);
  72.    
  73.     switch (sc) {
  74.     case SC_LSHIFT:
  75.     case SC_RSHIFT:
  76.         instance->keyflags &= ~PRESSED_SHIFT;
  77.         break;
  78.     case SC_CAPSLOCK:
  79.         instance->keyflags &= ~PRESSED_CAPSLOCK;
  80.         if (instance->lockflags & LOCKED_CAPSLOCK)
  81.             instance->lockflags &= ~LOCKED_CAPSLOCK;
  82.         else
  83.             instance->lockflags |= LOCKED_CAPSLOCK;
  84.         break;
  85.     default:
  86.         break;
  87.     }
  88.    
  89.     spinlock_unlock(&instance->keylock);
  90. }
  91.  
  92. /** Process keypress.
  93.  *
  94.  * @param sc Scancode of the key being pressed.
  95.  */
  96. static void key_pressed(kbrd_instance_t *instance, wchar_t sc)
  97. {
  98.     bool letter;
  99.     bool shift;
  100.     bool capslock;
  101.    
  102.     spinlock_lock(&instance->keylock);
  103.    
  104.     switch (sc) {
  105.     case SC_LSHIFT:
  106.     case SC_RSHIFT:
  107.         instance->keyflags |= PRESSED_SHIFT;
  108.         break;
  109.     case SC_CAPSLOCK:
  110.         instance->keyflags |= PRESSED_CAPSLOCK;
  111.         break;
  112.     case SC_SCAN_ESCAPE:
  113.         break;
  114.     default:
  115.         letter = islower(sc_primary_map[sc]);
  116.         shift = instance->keyflags & PRESSED_SHIFT;
  117.         capslock = (instance->keyflags & PRESSED_CAPSLOCK) ||
  118.             (instance->lockflags & LOCKED_CAPSLOCK);
  119.        
  120.         if ((letter) && (capslock))
  121.             shift = !shift;
  122.        
  123.         if (shift)
  124.             indev_push_character(instance->sink, sc_secondary_map[sc]);
  125.         else
  126.             indev_push_character(instance->sink, sc_primary_map[sc]);
  127.         break;
  128.     }
  129.    
  130.     spinlock_unlock(&instance->keylock);
  131. }
  132.  
  133. static void kkbrd(void *arg)
  134. {
  135.     static int key_released_flag = 0;
  136.     static int is_locked = 0;
  137.     kbrd_instance_t *instance = (kbrd_instance_t *) arg;
  138.    
  139.     while (true) {
  140.         wchar_t sc = indev_pop_character(&instance->raw);
  141.  
  142.         if (sc == PL050_KEY_RELEASE) {
  143.             key_released_flag = 1;
  144.         } else {
  145.             if (key_released_flag) {
  146.                 key_released_flag = 0;
  147.                 if (is_lock_key(sc)) {
  148.                     if (!is_locked) {
  149.                         is_locked = 1;
  150.                     } else {
  151.                         is_locked = 0;
  152.                         continue;
  153.                     }
  154.                 }
  155.                 key_released(instance, sc);
  156.  
  157.             } else {
  158.                 if (is_lock_key(sc) && is_locked)
  159.                     continue;
  160.                 key_pressed(instance, sc);
  161.             }
  162.         }
  163.        
  164.     }
  165. }
  166.  
  167. kbrd_instance_t *kbrd_init(void)
  168. {
  169.     kbrd_instance_t *instance
  170.         = malloc(sizeof(kbrd_instance_t), FRAME_ATOMIC);
  171.     if (instance) {
  172.         instance->thread
  173.             = thread_create(kkbrd, (void *) instance, TASK, 0, "kkbrd", false);
  174.        
  175.         if (!instance->thread) {
  176.             free(instance);
  177.             return NULL;
  178.         }
  179.        
  180.         instance->sink = NULL;
  181.         indev_initialize("kbrd", &instance->raw, &kbrd_raw_ops);
  182.        
  183.         spinlock_initialize(&instance->keylock, "instance_keylock");
  184.         instance->keyflags = 0;
  185.         instance->lockflags = 0;
  186.     }
  187.    
  188.     return instance;
  189. }
  190.  
  191. indev_t *kbrd_wire(kbrd_instance_t *instance, indev_t *sink)
  192. {
  193.     ASSERT(instance);
  194.     ASSERT(sink);
  195.    
  196.     instance->sink = sink;
  197.     thread_ready(instance->thread);
  198.    
  199.     return &instance->raw;
  200. }
  201.  
  202. static bool is_lock_key(wchar_t sc)
  203. {
  204.     return ((sc == PL050_CAPS_SCAN_CODE) || (sc == PL050_NUM_SCAN_CODE) ||
  205.         (sc == PL050_SCROLL_SCAN_CODE));
  206. }
  207.  
  208. /** @}
  209.  */
  210.