123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- /*
- * File : keyboard.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://openlab.rt-thread.com/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2006-09-15 QiuYi the first version
- * 2017-08-16 Parai the 2nd version
- */
- #include <rtthread.h>
- #include <rthw.h>
- #include <bsp.h>
- #include "keyboard.h"
- #include "keymap.h"
- #define FALSE RT_FALSE
- #define TRUE RT_TRUE
- #define PRIVATE static
- #define PUBLIC
- #define t_bool rt_bool_t
- #define t_8 rt_uint8_t
- #define t_32 rt_uint32_t
- PRIVATE KB_INPUT kb_in;
- PRIVATE t_bool code_with_E0 = FALSE;
- PRIVATE t_bool shift_l; /* l shift state */
- PRIVATE t_bool shift_r; /* r shift state */
- PRIVATE t_bool alt_l; /* l alt state */
- PRIVATE t_bool alt_r; /* r left state */
- PRIVATE t_bool ctrl_l; /* l ctrl state */
- PRIVATE t_bool ctrl_r; /* l ctrl state */
- PRIVATE t_bool caps_lock; /* Caps Lock */
- PRIVATE t_bool num_lock; /* Num Lock */
- PRIVATE t_bool scroll_lock; /* Scroll Lock */
- PRIVATE int column = 0; /* keyrow[column] is one value of keymap */
- PRIVATE t_8 get_byte_from_kb_buf();
- PRIVATE void set_leds();
- PRIVATE void kb_wait();
- PRIVATE void kb_ack();
- PUBLIC void init_keyboard()
- {
- kb_in.count = 0;
- kb_in.p_head = kb_in.p_tail = kb_in.buf;
- caps_lock = 0;
- num_lock = 1;
- scroll_lock = 0;
- set_leds();
- }
- PUBLIC rt_bool_t keyboard_read(rt_uint32_t *pkey)
- {
- t_8 scan_code;
- t_bool make; /* TRUE : make */
- /* FALSE: break */
- t_32 key = 0;
- t_32* keyrow;
- if(kb_in.count > 0){
- code_with_E0 = FALSE;
- scan_code = get_byte_from_kb_buf();
- /* start scan */
- if (scan_code == 0xE1) {
- int i;
- static const t_8 pausebreak_scan_code[] = {0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5};
- t_bool is_pausebreak = TRUE;
- for(i=1;i<6;i++){
- if (get_byte_from_kb_buf() != pausebreak_scan_code[i]) {
- is_pausebreak = FALSE;
- break;
- }
- }
- if (is_pausebreak) {
- key = PAUSEBREAK;
- }
- }
- else if (scan_code == 0xE0) {
- code_with_E0 = TRUE;
- scan_code = get_byte_from_kb_buf();
- /* PrintScreen pressed */
- if (scan_code == 0x2A) {
- code_with_E0 = FALSE;
- if ((scan_code = get_byte_from_kb_buf()) == 0xE0) {
- code_with_E0 = TRUE;
- if ((scan_code = get_byte_from_kb_buf()) == 0x37) {
- key = PRINTSCREEN;
- make = TRUE;
- }
- }
- }
- /* PrintScreen released */
- else if (scan_code == 0xB7) {
- code_with_E0 = FALSE;
- if ((scan_code = get_byte_from_kb_buf()) == 0xE0) {
- code_with_E0 = TRUE;
- if ((scan_code = get_byte_from_kb_buf()) == 0xAA) {
- key = PRINTSCREEN;
- make = FALSE;
- }
- }
- }
- } /* if is not PrintScreen, scan_code is the one after 0xE0 */
- if ((key != PAUSEBREAK) && (key != PRINTSCREEN)) {
- /* is Make Code or Break Code */
- make = (scan_code & FLAG_BREAK ? FALSE : TRUE);
-
- keyrow = &keymap[(scan_code & 0x7F) * MAP_COLS];
- column = 0;
- t_bool caps = shift_l || shift_r;
- if (caps_lock) {
- if ((keyrow[0] >= 'a') && (keyrow[0] <= 'z')){
- caps = !caps;
- }
- }
- if (caps) {
- column = 1;
- }
- if (code_with_E0) {
- column = 2;
- }
- key = keyrow[column];
- switch(key) {
- case SHIFT_L:
- shift_l = make;
- break;
- case SHIFT_R:
- shift_r = make;
- break;
- case CTRL_L:
- ctrl_l = make;
- break;
- case CTRL_R:
- ctrl_r = make;
- break;
- case ALT_L:
- alt_l = make;
- break;
- case ALT_R:
- alt_l = make;
- break;
- case CAPS_LOCK:
- if (make) {
- caps_lock = !caps_lock;
- set_leds();
- }
- break;
- case NUM_LOCK:
- if (make) {
- num_lock = !num_lock;
- set_leds();
- }
- break;
- case SCROLL_LOCK:
- if (make) {
- scroll_lock = !scroll_lock;
- set_leds();
- }
- break;
- default:
- break;
- }
- }
- if(make){ /* ignore Break Code */
- t_bool pad = FALSE;
- /* handle the small pad first */
- if ((key >= PAD_SLASH) && (key <= PAD_9)) {
- pad = TRUE;
- switch(key) { /* '/', '*', '-', '+', and 'Enter' in num pad */
- case PAD_SLASH:
- key = '/';
- break;
- case PAD_STAR:
- key = '*';
- break;
- case PAD_MINUS:
- key = '-';
- break;
- case PAD_PLUS:
- key = '+';
- break;
- case PAD_ENTER:
- key = ENTER;
- break;
- default: /* keys whose value depends on the NumLock */
- if (num_lock) { /* '0' ~ '9' and '.' in num pad */
- if ((key >= PAD_0) && (key <= PAD_9)) {
- key = key - PAD_0 + '0';
- }
- else if (key == PAD_DOT) {
- key = '.';
- }
- }
- else{
- switch(key) {
- case PAD_HOME:
- key = HOME;
- break;
- case PAD_END:
- key = END;
- break;
- case PAD_PAGEUP:
- key = PAGEUP;
- break;
- case PAD_PAGEDOWN:
- key = PAGEDOWN;
- break;
- case PAD_INS:
- key = INSERT;
- break;
- case PAD_UP:
- key = UP;
- break;
- case PAD_DOWN:
- key = DOWN;
- break;
- case PAD_LEFT:
- key = LEFT;
- break;
- case PAD_RIGHT:
- key = RIGHT;
- break;
- case PAD_DOT:
- key = DELETE;
- break;
- default:
- break;
- }
- }
- break;
- }
- }
- key |= shift_l ? FLAG_SHIFT_L : 0;
- key |= shift_r ? FLAG_SHIFT_R : 0;
- key |= ctrl_l ? FLAG_CTRL_L : 0;
- key |= ctrl_r ? FLAG_CTRL_R : 0;
- key |= alt_l ? FLAG_ALT_L : 0;
- key |= alt_r ? FLAG_ALT_R : 0;
- key |= pad ? FLAG_PAD : 0;
- *pkey = key;
- return TRUE;
- }
- }
- return FALSE;
- }
- PRIVATE t_8 get_byte_from_kb_buf()
- {
- t_8 scan_code;
- RT_ASSERT(kb_in.count>0);
- scan_code = *(kb_in.p_tail);
- kb_in.p_tail++;
- if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES) {
- kb_in.p_tail = kb_in.buf;
- }
- kb_in.count--;
- return scan_code;
- }
- PRIVATE void kb_wait() /* wait inpit cache of 8042 */
- {
- t_8 kb_stat;
- do {
- kb_stat = inb(KB_CMD);
- } while (kb_stat & 0x02);
- }
- PRIVATE void kb_ack()
- {
- t_8 kb_read;
- do {
- kb_read = inb(KB_DATA);
- } while (kb_read != KB_ACK);
- }
- PRIVATE void set_leds()
- {
- t_8 leds = (caps_lock << 2) | (num_lock << 1) | scroll_lock;
- kb_wait();
- outb(KB_DATA, LED_CODE);
- kb_ack();
- kb_wait();
- outb(KB_DATA, leds);
- kb_ack();
- }
- /**
- * @addtogroup QEMU
- */
- /*@{*/
- void rt_keyboard_isr(void)
- {
- rt_uint8_t data;
- if ((inb(KBSTATP) & KBS_DIB) == 0)
- return ;
- data = inb(KBDATAP);
- if (kb_in.count < KB_IN_BYTES) {
- *(kb_in.p_head) = data;
- kb_in.p_head++;
- if (kb_in.p_head == kb_in.buf + KB_IN_BYTES) {
- kb_in.p_head = kb_in.buf;
- }
- kb_in.count++;
- }
- }
- /* generally, this should be called in task level for all key inpit support,
- but here only support a key that is composed of 2 bytes */
- rt_bool_t rt_keyboard_getc(char* c)
- {
- if(kb_in.count>=2)
- {
- rt_uint32_t key = 0;
- rt_bool_t rv=keyboard_read(&key);
- switch(key)
- {
- case TAB:
- *c = '\t';
- break;
- case ENTER:
- *c = '\n';
- break;
- case BACKSPACE:
- *c = '\b';
- break;
- default:
- *c = key;
- break;
- }
- return rv;
- }
- return RT_FALSE;
- }
- /*@}*/
|