Add kbd_peekMask() and kbd_getMask() functions.
[bertos.git] / bertos / drv / kbd.c
index 19b2478df313275725165039a4bfb12903176d52..b75db360354c82214de1c2c1550bb02ff0bbb45c 100644 (file)
@@ -33,7 +33,6 @@
  *
  * \brief Keyboard driver (implementation)
  *
- * \version $Id$
  *
  * \author Bernie Innocenti <bernie@codewiz.org>
  * \author Stefano Fedrigo <aleph@develer.com>
@@ -48,6 +47,7 @@
 #include <cfg/module.h>
 
 #include <drv/timer.h>
+#include <mware/event.h>
 #include <drv/kbd.h>
 
 
@@ -84,6 +84,8 @@
 /** Status for keyboard repeat state machine */
 static enum { KS_IDLE, KS_REPDELAY, KS_REPEAT } kbd_rptStatus;
 
+/** Used to notify the occurrence of a key pressed event */
+static Event key_pressed;
 
 static volatile keymask_t kbd_buf; /**< Single entry keyboard buffer */
 static volatile keymask_t kbd_cnt; /**< Number of keypress events in \c kbd_buf */
@@ -174,19 +176,29 @@ static void kbd_softint(UNUSED_ARG(iptr_t, arg))
  *
  */
 keymask_t kbd_peek(void)
+{
+       return kbd_peekMask((keymask_t)0xFFFFFFFFFFFFFFFFULL);
+}
+
+
+keymask_t kbd_peekMask(keymask_t mask)
 {
        keymask_t key = 0;
 
 #if CONFIG_KBD_SCHED
+       /* Let other tasks run for a while */
+       extern void schedule(void);
        schedule();
 #endif
 
        /* Extract an event from the keyboard buffer */
        IRQ_DISABLE;
-       if (kbd_cnt)
+       if (kbd_cnt && (kbd_buf & mask))
        {
-               --kbd_cnt;
-               key = kbd_buf;
+               key = kbd_buf & mask;
+               kbd_buf &= ~mask;
+               if (!kbd_buf)
+                       --kbd_cnt;
        }
        IRQ_ENABLE;
 
@@ -199,10 +211,25 @@ keymask_t kbd_peek(void)
  * \note This function is \b not interrupt safe!
  */
 keymask_t kbd_get(void)
+{
+       return kbd_getMask((keymask_t)0xFFFFFFFFFFFFFFFFULL);
+}
+
+keymask_t kbd_getMask(keymask_t mask)
 {
        keymask_t key;
 
-       while (!(key = kbd_peek())) {}
+       #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT
+               do
+               {
+                       event_wait(&key_pressed);
+                       key = kbd_peekMask(mask);
+               }
+               while (!key);
+       #else
+               while (!(key = kbd_peekMask(mask)))
+                       cpu_relax();
+       #endif
 
        return key;
 }
@@ -215,18 +242,10 @@ keymask_t kbd_get(void)
  */
 keymask_t kbd_get_timeout(mtime_t timeout)
 {
-       keymask_t key;
-
-       ticks_t start = timer_clock();
-       ticks_t stop  = ms_to_ticks(timeout);
-       do
-       {
-               if ((key = kbd_peek()))
-                       return key;
-       }
-       while (timer_clock() - start < stop);
-
-       return K_TIMEOUT;
+       if (event_waitTimeout(&key_pressed, timeout))
+               return kbd_peek();
+       else
+               return K_TIMEOUT;
 }
 
 
@@ -277,6 +296,9 @@ static keymask_t kbd_defHandlerFunc(keymask_t key)
                /* Force a single event in kbd buffer */
                kbd_buf = key;
                kbd_cnt = 1;
+               #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT
+                       event_do(&key_pressed);
+               #endif
 
                #if CONFIG_KBD_OBSERVER
                        observer_notify(&kbd_subject, KBD_EVENT_KEY, &key);
@@ -470,6 +492,12 @@ void kbd_init(void)
 #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT
 
        MOD_CHECK(timer);
+       #if CONFIG_KERN
+               MOD_CHECK(proc);
+       #endif
+
+       /* Initialize the keyboard event (key pressed) */
+       event_initGeneric(&key_pressed);
 
        /* Add kbd handler to soft timers list */
        event_initSoftint(&kbd_timer.expire, kbd_softint, NULL);