BeRTOS
|
00001 00043 #include "hw/hw_kbd.h" 00044 00045 #include "cfg/cfg_kbd.h" 00046 #include <cfg/debug.h> 00047 #include <cfg/module.h> 00048 00049 #include <drv/timer.h> 00050 #include <mware/event.h> 00051 #include <drv/kbd.h> 00052 00053 00054 /* Configuration sanity checks */ 00055 #if !defined(CONFIG_KBD_POLL) || (CONFIG_KBD_POLL != KBD_POLL_SOFTINT) 00056 #error CONFIG_KBD_POLL must be defined to either KBD_POLL_SOFTINT 00057 #endif 00058 #if !defined(CONFIG_KBD_BEEP) || (CONFIG_KBD_BEEP != 0 && CONFIG_KBD_BEEP != 1) 00059 #error CONFIG_KBD_BEEP must be defined to either 0 or 1 00060 #endif 00061 #if !defined(CONFIG_KBD_OBSERVER) || (CONFIG_KBD_OBSERVER != 0 && CONFIG_KBD_OBSERVER != 1) 00062 #error CONFIG_KBD_OBSERVER must be defined to either 0 or 1 00063 #endif 00064 #if !defined(CONFIG_KBD_LONGPRESS) || (CONFIG_KBD_LONGPRESS != 0 && CONFIG_KBD_LONGPRESS != 1) 00065 #error CONFIG_KBD_LONGPRESS must be defined to either 0 or 1 00066 #endif 00067 00068 #if CONFIG_KBD_BEEP 00069 #include <drv/buzzer.h> 00070 #endif 00071 00072 #define KBD_CHECK_INTERVAL 10 00073 #define KBD_DEBOUNCE_TIME 30 00074 #define KBD_BEEP_TIME 5 00076 #define KBD_REPEAT_DELAY 400 00077 #define KBD_REPEAT_RATE 100 00078 #define KBD_REPEAT_MAXRATE 20 00079 #define KBD_REPEAT_ACCEL 5 00081 #define KBD_LNG_DELAY 1000 00085 static enum { KS_IDLE, KS_REPDELAY, KS_REPEAT } kbd_rptStatus; 00086 00088 static Event key_pressed; 00089 00090 static volatile keymask_t kbd_buf; 00091 static volatile keymask_t kbd_cnt; 00092 static keymask_t kbd_rpt_mask; 00094 #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT 00095 static Timer kbd_timer; 00096 #endif 00097 00098 static List kbd_rawHandlers; 00099 static List kbd_handlers; 00101 static KbdHandler kbd_defHandler; 00102 static KbdHandler kbd_debHandler; 00103 static KbdHandler kbd_rptHandler; 00105 #if CONFIG_KBD_LONGPRESS 00106 static KbdHandler kbd_lngHandler; 00107 #endif 00108 00109 #if CONFIG_KBD_OBSERVER 00110 #include <mware/observer.h> 00111 Subject kbd_subject; 00112 #endif 00113 00114 00124 static void kbd_poll(void) 00125 { 00127 static keymask_t current_key; 00128 00129 struct KbdHandler *handler; 00130 keymask_t key = kbd_readkeys(); 00131 00132 /* Call raw input handlers */ 00133 FOREACH_NODE(handler, &kbd_rawHandlers) 00134 key = handler->hook(key); 00135 00136 /* If this key was not previously pressed */ 00137 if (key != current_key) 00138 { 00139 /* Remember last key */ 00140 current_key = key; 00141 00142 /* Call cooked input handlers */ 00143 FOREACH_NODE(handler, &kbd_handlers) 00144 key = handler->hook(key); 00145 } 00146 } 00147 00148 #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT 00149 00153 static void kbd_softint(UNUSED_ARG(iptr_t, arg)) 00154 { 00155 kbd_poll(); 00156 timer_add(&kbd_timer); 00157 } 00158 00159 #else 00160 #error "Define keyboard poll method" 00161 00162 #endif /* CONFIG_KBD_POLL */ 00163 00178 keymask_t kbd_peek(void) 00179 { 00180 keymask_t key = 0; 00181 00182 #if CONFIG_KBD_SCHED 00183 /* Let other tasks run for a while */ 00184 extern void schedule(void); 00185 schedule(); 00186 #endif 00187 00188 /* Extract an event from the keyboard buffer */ 00189 IRQ_DISABLE; 00190 if (kbd_cnt) 00191 { 00192 --kbd_cnt; 00193 key = kbd_buf; 00194 } 00195 IRQ_ENABLE; 00196 00197 return key; 00198 } 00199 00205 keymask_t kbd_get(void) 00206 { 00207 keymask_t key; 00208 00209 #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT 00210 event_wait(&key_pressed); 00211 key = kbd_peek(); 00212 #else 00213 while (!(key = kbd_peek())) 00214 cpu_relax(); 00215 #endif 00216 00217 return key; 00218 } 00219 00220 00226 keymask_t kbd_get_timeout(mtime_t timeout) 00227 { 00228 if (event_waitTimeout(&key_pressed, timeout)) 00229 return kbd_peek(); 00230 else 00231 return K_TIMEOUT; 00232 } 00233 00234 00235 void kbd_addHandler(struct KbdHandler *handler) 00236 { 00237 KbdHandler *node; 00238 List *list; 00239 00240 cpu_flags_t flags; 00241 IRQ_SAVE_DISABLE(flags); 00242 00243 /* Choose between raw and coocked handlers list */ 00244 list = (handler->flags & KHF_RAWKEYS) ? 00245 &kbd_rawHandlers : &kbd_handlers; 00246 00247 /* 00248 * Search for the first node whose priority 00249 * is lower than the timer we want to add. 00250 */ 00251 FOREACH_NODE(node,list) 00252 if (node->pri < handler->pri) 00253 break; 00254 00255 /* Enqueue handler in the handlers chain */ 00256 INSERT_BEFORE(&handler->link, &node->link); 00257 00258 IRQ_RESTORE(flags); 00259 } 00260 00261 00262 void kbd_remHandler(struct KbdHandler *handler) 00263 { 00264 /* Remove the handler */ 00265 ATOMIC(REMOVE(&handler->link)); 00266 } 00267 00268 00275 static keymask_t kbd_defHandlerFunc(keymask_t key) 00276 { 00277 if (key) 00278 { 00279 /* Force a single event in kbd buffer */ 00280 kbd_buf = key; 00281 kbd_cnt = 1; 00282 #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT 00283 event_do(&key_pressed); 00284 #endif 00285 00286 #if CONFIG_KBD_OBSERVER 00287 observer_notify(&kbd_subject, KBD_EVENT_KEY, &key); 00288 #endif 00289 00290 #if CONFIG_KBD_BEEP 00291 if (!(key & K_REPEAT)) 00292 buz_beep(KBD_BEEP_TIME); 00293 #endif 00294 } 00295 00296 /* Eat all input */ 00297 return 0; 00298 } 00299 00303 static keymask_t kbd_debHandlerFunc(keymask_t key) 00304 { 00306 static keymask_t debounce_key; 00307 00309 static ticks_t debounce_time; 00310 00312 static keymask_t new_key; 00313 00314 00315 ticks_t now = timer_clock(); 00316 00317 if (key != debounce_key) 00318 { 00319 /* Reset debounce timer */ 00320 debounce_key = key; 00321 debounce_time = now; 00322 } 00323 else if ((new_key != debounce_key) 00324 && (now - debounce_time > ms_to_ticks(KBD_DEBOUNCE_TIME))) 00325 { 00326 new_key = debounce_key; 00327 debounce_time = now; 00328 } 00329 00330 return new_key; 00331 } 00332 00333 #if CONFIG_KBD_LONGPRESS 00334 00337 static keymask_t kbd_lngHandlerFunc(keymask_t key) 00338 { 00339 static ticks_t start; 00340 ticks_t now = timer_clock(); 00341 00342 if (key & K_LNG_MASK) 00343 { 00344 if (now - start > ms_to_ticks(KBD_LNG_DELAY)) 00345 key |= K_LONG; 00346 } 00347 else 00348 start = now; 00349 return key; 00350 } 00351 #endif 00352 00356 keymask_t kbd_setRepeatMask(keymask_t mask) 00357 { 00358 keymask_t oldmask = kbd_rpt_mask; 00359 ATOMIC(kbd_rpt_mask = mask); 00360 return oldmask; 00361 } 00362 00366 static keymask_t kbd_rptHandlerFunc(keymask_t key) 00367 { 00368 /* Timer for keyboard repeat events. */ 00369 static ticks_t repeat_time; 00370 00371 /* Current repeat rate (for acceleration). */ 00372 static ticks_t repeat_rate; 00374 ticks_t now = timer_clock(); 00375 00376 switch (kbd_rptStatus) 00377 { 00378 case KS_IDLE: 00379 if (key & kbd_rpt_mask) 00380 { 00381 repeat_time = now; 00382 kbd_rptStatus = KS_REPDELAY; 00383 } 00384 break; 00385 00386 case KS_REPDELAY: 00387 if (key & kbd_rpt_mask) 00388 { 00389 if (now - repeat_time > ms_to_ticks(KBD_REPEAT_DELAY)) 00390 { 00391 key = (key & kbd_rpt_mask) | K_REPEAT; 00392 repeat_time = now; 00393 repeat_rate = ms_to_ticks(KBD_REPEAT_RATE); 00394 kbd_rptStatus = KS_REPEAT; 00395 } 00396 else 00397 key = 0; 00398 } 00399 else 00400 kbd_rptStatus = KS_IDLE; 00401 break; 00402 00403 case KS_REPEAT: 00404 if (key & kbd_rpt_mask) 00405 { 00406 if (now - repeat_time > repeat_rate) 00407 { 00408 /* Enqueue a new event in the buffer */ 00409 key = (key & kbd_rpt_mask) | K_REPEAT; 00410 repeat_time = now; 00411 00412 /* Repeat rate acceleration */ 00413 if (repeat_rate > ms_to_ticks(KBD_REPEAT_MAXRATE)) 00414 repeat_rate -= ms_to_ticks(KBD_REPEAT_ACCEL); 00415 } 00416 else 00417 key = 0; 00418 } 00419 else 00420 kbd_rptStatus = KS_IDLE; 00421 00422 break; 00423 } 00424 00425 return key; 00426 } 00427 00428 00429 MOD_DEFINE(kbd) 00430 00431 00434 void kbd_init(void) 00435 { 00436 #if CONFIG_KBD_BEEP 00437 MOD_CHECK(buzzer); 00438 #endif 00439 00440 KBD_HW_INIT; 00441 00442 /* Init handlers lists */ 00443 LIST_INIT(&kbd_handlers); 00444 LIST_INIT(&kbd_rawHandlers); 00445 00446 /* Add debounce keyboard handler */ 00447 kbd_debHandler.hook = kbd_debHandlerFunc; 00448 kbd_debHandler.pri = 100; /* high priority */ 00449 kbd_debHandler.flags = KHF_RAWKEYS; 00450 kbd_addHandler(&kbd_debHandler); 00451 00452 #if CONFIG_KBD_LONGPRESS 00453 /* Add long pression keyboard handler */ 00454 kbd_lngHandler.hook = kbd_lngHandlerFunc; 00455 kbd_lngHandler.pri = 90; /* high priority */ 00456 kbd_lngHandler.flags = KHF_RAWKEYS; 00457 kbd_addHandler(&kbd_lngHandler); 00458 #endif 00459 00460 /* Add repeat keyboard handler */ 00461 kbd_rptHandler.hook = kbd_rptHandlerFunc; 00462 kbd_rptHandler.pri = 80; /* high priority */ 00463 kbd_rptHandler.flags = KHF_RAWKEYS; 00464 kbd_addHandler(&kbd_rptHandler); 00465 00466 /* Add default keyboard handler */ 00467 kbd_defHandler.hook = kbd_defHandlerFunc; 00468 kbd_defHandler.pri = -128; /* lowest priority */ 00469 kbd_addHandler(&kbd_defHandler); 00470 00471 #if CONFIG_KBD_OBSERVER 00472 observer_InitSubject(&kbd_subject); 00473 #endif 00474 00475 #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT 00476 00477 MOD_CHECK(timer); 00478 #if CONFIG_KERN 00479 MOD_CHECK(proc); 00480 #endif 00481 00482 /* Initialize the keyboard event (key pressed) */ 00483 event_initGeneric(&key_pressed); 00484 00485 /* Add kbd handler to soft timers list */ 00486 event_initSoftint(&kbd_timer.expire, kbd_softint, NULL); 00487 timer_setDelay(&kbd_timer, ms_to_ticks(KBD_CHECK_INTERVAL)); 00488 timer_add(&kbd_timer); 00489 00490 #else 00491 #error "Define keyboard poll method" 00492 00493 #endif 00494 00495 MOD_INIT(kbd); 00496 }