123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- #include <rthw.h>
- #include <rtthread.h>
- #include <rtdevice.h>
- #include "board.h"
- #include "interrupt.h"
- #include "drv_keyboard.h"
- #define DBG_LEVEL DBG_INFO
- #include "rtdbg.h"
- #define KEYBOARD_ADDRESS (0x10006000)
- #define KEYBOARD_IRQ_NUM (IRQ_VEXPRESS_A9_KBD)
- #ifdef PKG_USING_GUIENGINE
- #include <rtgui/event.h>
- #include <rtgui/rtgui_server.h>
- typedef rt_uint32_t virtual_addr_t;
- enum{
- KEYBOARD_CR = 0x00,
- KEYBOARD_STAT = 0x04,
- KEYBOARD_DATA = 0x08,
- KEYBOARD_CLKDIV = 0x0c,
- KEYBOARD_IIR = 0x10,
- };
- struct keyboard_pl050_pdata_t
- {
- virtual_addr_t virt;
- int irq;
- };
- enum decode_state {
- DECODE_STATE_MAKE_CODE,
- DECODE_STATE_BREAK_CODE,
- DECODE_STATE_LONG_MAKE_CODE,
- DECODE_STATE_LONG_BREAK_CODE
- };
- struct keymap {
- rt_uint8_t data;
- rt_uint32_t key;
- rt_uint32_t unicode;
- char *normal_key;
- };
- enum key_value_t {
- KEY_BUTTON_UP,
- KEY_BUTTON_DOWN,
- };
- enum {
- KBD_LEFT_SHIFT = (0x1 << 0),
- KBD_RIGHT_SHIFT = (0x1 << 1),
- KBD_LEFT_CTRL = (0x1 << 2),
- KBD_RIGHT_CTRL = (0x1 << 3),
- KBD_CAPS_LOCK = (0x1 << 6),
- KBD_NUM_LOCK = (0x1 << 7),
- KBD_SCROLL_LOCK = (0x1 << 8),
- };
- static const struct keymap map[] = {
- {0x1c, RTGUIK_a, 0, "a", },
- {0x32, RTGUIK_b, 0, "b", },
- {0x21, RTGUIK_c, 0, "c", },
- {0x23, RTGUIK_d, 0, "d", },
- {0x24, RTGUIK_e, 0, "e", },
- {0x2b, RTGUIK_f, 0, "f", },
- {0x34, RTGUIK_g, 0, "g", },
- {0x33, RTGUIK_h, 0, "h", },
- {0x43, RTGUIK_i, 0, "i", },
- {0x3b, RTGUIK_j, 0, "j", },
- {0x42, RTGUIK_k, 0, "k", },
- {0x4b, RTGUIK_l, 0, "l", },
- {0x3a, RTGUIK_m, 0, "m", },
- {0x31, RTGUIK_n, 0, "n", },
- {0x44, RTGUIK_o, 0, "o", },
- {0x4d, RTGUIK_p, 0, "p", },
- {0x15, RTGUIK_q, 0, "q", },
- {0x2d, RTGUIK_r, 0, "r", },
- {0x1b, RTGUIK_s, 0, "s", },
- {0x2c, RTGUIK_k, 0, "k", },
- {0x3c, RTGUIK_u, 0, "u", },
- {0x2a, RTGUIK_v, 0, "v", },
- {0x1d, RTGUIK_w, 0, "w", },
- {0x22, RTGUIK_x, 0, "x", },
- {0x35, RTGUIK_y, 0, "y", },
- {0x1a, RTGUIK_z, 0, "z", },
- {0x45, RTGUIK_0, 0, "0", },
- {0x16, RTGUIK_1, 0, "1", },
- {0x1e, RTGUIK_2, 0, "2", },
- {0x26, RTGUIK_3, 0, "3", },
- {0x25, RTGUIK_4, 0, "4", },
- {0x2e, RTGUIK_5, 0, "5", },
- {0x36, RTGUIK_6, 0, "6", },
- {0x3d, RTGUIK_7, 0, "7", },
- {0x3e, RTGUIK_8, 0, "8", },
- {0x46, RTGUIK_9, 0, "9", },
- {0x05, RTGUIK_F1, 0, "F1", },
- {0x06, RTGUIK_F2, 0, "F2", },
- {0x04, RTGUIK_F3, 0, "F3", },
- {0x0c, RTGUIK_F4, 0, "F4", },
- {0x03, RTGUIK_F5, 0, "F5", },
- {0x0b, RTGUIK_F6, 0, "F6", },
- {0x83, RTGUIK_F7, 0, "F7", },
- {0x0a, RTGUIK_F8, 0, "F8", },
- {0x01, RTGUIK_F9, 0, "F9", },
- {0x09, RTGUIK_F10, 0, "F10", },
- {0x78, RTGUIK_F11, 0, "F11", },
- {0x07, RTGUIK_F12, 0, "F12", },
- {0x29, RTGUIK_SPACE, 0, "SPACE" },
- {0x71, RTGUIK_DELETE, 0, "DELETE" },
- {0x52, RTGUIK_QUOTE, 0, "'" },
- {0x55, RTGUIK_EQUALS, 0, "=" },
- {0x41, RTGUIK_COMMA, 0, "," },
- {0x4e, RTGUIK_MINUS, 0, "-" },
- // {0x49, RTGUIK_, 0, "." },
- {0x4a, RTGUIK_SLASH, 0, "/" },
- {0x4c, RTGUIK_SEMICOLON, 0, ";" },
- {0x54, RTGUIK_LEFTBRACKET, 0, "[" },
- {0x5d, RTGUIK_BACKSLASH, 0, "\\" },
- {0x5b, RTGUIK_RIGHTBRACKET, 0, "]"},
- {0x75, RTGUIK_UP, 0, "UP" },
- {0x72, RTGUIK_DOWN, 0, "DOWN" },
- {0x6b, RTGUIK_LEFT, 0, "LEFT" },
- {0x74, RTGUIK_RIGHT, 0, "RIGHT" },
- {0x0d, RTGUIK_TAB, 0, "TAB" },
- {0x76, RTGUIK_ESCAPE, 0, "ESC" },
- {0x37, RTGUIK_POWER, 0, "POWER" },
- {0x5a, RTGUIK_KP_ENTER, 0, "ENTER"},
- {0x66, RTGUIK_BACKSPACE, 0, "BACKSPACE"},
- };
- rt_inline rt_uint8_t read8(uint32_t addr)
- {
- return (*((volatile rt_uint8_t *)(addr)));
- }
- rt_inline void write8(uint32_t addr, rt_uint8_t value)
- {
- *((volatile rt_uint8_t *)(addr)) = value;
- }
- rt_inline rt_uint32_t read32(uint32_t addr)
- {
- return (*((volatile rt_uint32_t *)(addr)));
- }
- rt_inline void write32(uint32_t addr, rt_uint32_t value)
- {
- *((volatile rt_uint32_t *)(addr)) = value;
- }
- rt_inline int kmi_write(struct keyboard_pl050_pdata_t * pdat, rt_uint8_t value)
- {
- int timeout = 1000;
- while((read8(pdat->virt + KEYBOARD_STAT) & (1 << 6)) == 0 && timeout--);
- if(timeout)
- {
- write8(pdat->virt + KEYBOARD_DATA, value);
- while((read8(pdat->virt + KEYBOARD_STAT) & (1 << 4)) == 0);
- if(read8(pdat->virt + KEYBOARD_DATA) == 0xfa)
- return RT_TRUE;
- }
- return RT_FALSE;
- }
- rt_inline int kmi_read(struct keyboard_pl050_pdata_t * pdat, rt_uint8_t * value)
- {
- if((read8(pdat->virt + KEYBOARD_STAT) & (1 << 4)))
- {
- *value = read8(pdat->virt + KEYBOARD_DATA);
- return RT_TRUE;
- }
- return RT_FALSE;
- }
- static void keyboard_report_event(void * device, rt_uint32_t flag, rt_uint8_t data, enum key_value_t press)
- {
- struct rtgui_event_kbd key_event;
- rt_uint16_t i = 0, mod = 0, find_key = 0;
- for(i = 0; i < sizeof(map)/sizeof(map[0]); i++)
- {
- if (map[i].data == data)
- {
- LOG_D("KEY info:");
- if (flag & KBD_CAPS_LOCK)
- {
- LOG_D("CAPS:LOCK");
- }
- else
- {
- LOG_D("CAPS:UNLOCK");
- }
- if (flag & KBD_LEFT_SHIFT)
- {
- mod |= RTGUI_KMOD_LSHIFT;
- LOG_D("SHIFT:LEFT");
- }
- else if (flag & KBD_RIGHT_SHIFT)
- {
- mod |= RTGUI_KMOD_RSHIFT;
- LOG_D("SHIFT:RIGHT");
- }
- else
- {
- LOG_D("SHIFT:NULL");
- }
- if (flag & KBD_LEFT_CTRL)
- {
- mod |= RTGUI_KMOD_LCTRL;
- LOG_D("CTRL:LEFT");
- }
- else if (flag & KBD_RIGHT_CTRL)
- {
- mod |= RTGUI_KMOD_RCTRL;
- LOG_D("CTRL:RIGHT");
- }
- else
- {
- LOG_D("CTRL:NULL");
- }
- LOG_D("flag:0x%08x value:0x%x key:%s status:%s", \
- flag, data, map[i].normal_key, press ==0 ? "UP" : "DOWN");
- find_key = 1;
- break;
- }
- }
- if (find_key == 0)
- {
- LOG_D("flag:0x%08x value:0x%x key:%s status:%s", \
- flag, data, "UNKNOWN", press ==0 ? "UP" : "DOWN");
- return;
- }
- key_event.parent.sender = RT_NULL;
- key_event.parent.type = RTGUI_EVENT_KBD;
- key_event.type = (press == 0 ? RTGUI_KEYUP : RTGUI_KEYDOWN);
- key_event.key = map[i].key;
- key_event.mod = mod;
- key_event.unicode = map[i].unicode;
- rtgui_server_post_event(&key_event.parent, sizeof(key_event));
- }
- static void keyboard_pl050_interrupt(int irq, void *data)
- {
- struct keyboard_pl050_pdata_t * pdat = (struct keyboard_pl050_pdata_t *)data;
- static enum decode_state ds = DECODE_STATE_MAKE_CODE;
- static rt_uint32_t kbd_flag = KBD_NUM_LOCK;
- rt_uint8_t status, value;
- status = read8(pdat->virt + KEYBOARD_IIR);
- while(status & (1 << 0))
- {
- value = read8(pdat->virt + KEYBOARD_DATA);
- switch(ds)
- {
- case DECODE_STATE_MAKE_CODE:
- /* break code */
- if(value == 0xf0)
- {
- ds = DECODE_STATE_BREAK_CODE;
- }
- /* long make code */
- else if(value == 0xe0)
- {
- ds = DECODE_STATE_LONG_MAKE_CODE;
- }
- else
- {
- ds = DECODE_STATE_MAKE_CODE;
- /* left shift */
- if(value == 0x12)
- {
- kbd_flag |= KBD_LEFT_SHIFT;
- }
- /* right shift */
- else if(value == 0x59)
- {
- kbd_flag |= KBD_RIGHT_SHIFT;
- }
- /* left ctrl */
- else if(value == 0x14)
- {
- kbd_flag |= KBD_LEFT_CTRL;
- }
- /* caps lock */
- else if(value == 0x58)
- {
- if(kbd_flag & KBD_CAPS_LOCK)
- kbd_flag &= ~KBD_CAPS_LOCK;
- else
- kbd_flag |= KBD_CAPS_LOCK;
- }
- /* scroll lock */
- else if(value == 0x7e)
- {
- if(kbd_flag & KBD_SCROLL_LOCK)
- kbd_flag &= ~KBD_SCROLL_LOCK;
- else
- kbd_flag |= KBD_SCROLL_LOCK;
- }
- /* num lock */
- else if(value == 0x77)
- {
- if(kbd_flag & KBD_NUM_LOCK)
- kbd_flag &= ~KBD_NUM_LOCK;
- else
- kbd_flag |= KBD_NUM_LOCK;
- }
- /* others */
- else
- {
- keyboard_report_event(data, kbd_flag, value, KEY_BUTTON_DOWN);
- }
- }
- break;
- case DECODE_STATE_BREAK_CODE:
- if( (value != 0xf0) && (value != 0xe0))
- {
- ds = DECODE_STATE_MAKE_CODE;
- /* left shift */
- if(value == 0x12)
- {
- kbd_flag &= ~KBD_LEFT_SHIFT;
- }
- /* right shift */
- else if(value == 0x59)
- {
- kbd_flag &= ~KBD_RIGHT_SHIFT;
- }
- /* left ctrl */
- else if(value == 0x14)
- {
- kbd_flag &= ~KBD_LEFT_CTRL;
- }
- /* others */
- else
- {
- keyboard_report_event(data, kbd_flag, value, KEY_BUTTON_UP);
- }
- }
- else
- {
- ds = DECODE_STATE_BREAK_CODE;
- }
- break;
- case DECODE_STATE_LONG_MAKE_CODE:
- if( value != 0xf0 && value!= 0xe0)
- {
- ds = DECODE_STATE_MAKE_CODE;
- /* left ctrl */
- if(value == 0x14)
- {
- kbd_flag |= KBD_RIGHT_CTRL;
- }
- /* others */
- else
- {
- keyboard_report_event(data, kbd_flag, value, KEY_BUTTON_DOWN);
- }
- }
- else
- {
- ds = DECODE_STATE_LONG_BREAK_CODE;
- }
- break;
- case DECODE_STATE_LONG_BREAK_CODE:
- if( (value != 0xf0) && (value != 0xe0))
- {
- ds = DECODE_STATE_MAKE_CODE;
- /* left ctrl */
- if(value == 0x14)
- {
- kbd_flag &= ~KBD_RIGHT_CTRL;
- }
- /* others */
- else
- {
- keyboard_report_event(data, kbd_flag, value, KEY_BUTTON_UP);
- }
- }
- else
- {
- ds = DECODE_STATE_LONG_BREAK_CODE;
- }
- break;
- default:
- ds = DECODE_STATE_MAKE_CODE;
- break;
- }
- status = read8(pdat->virt + KEYBOARD_IIR);
- }
- }
- int rt_hw_keyboard_init(void)
- {
- rt_uint8_t value;
- rt_uint32_t id;
- struct keyboard_pl050_pdata_t *pdat;
- virtual_addr_t virt = (virtual_addr_t)KEYBOARD_ADDRESS;
- int irq = KEYBOARD_IRQ_NUM;
-
- id = (((read32(virt + 0xfec) & 0xff) << 24) |
- ((read32(virt + 0xfe8) & 0xff) << 16) |
- ((read32(virt + 0xfe4) & 0xff) << 8) |
- ((read32(virt + 0xfe0) & 0xff) << 0));
-
- if(((id >> 12) & 0xff) != 0x41 || (id & 0xfff) != 0x050)
- {
- LOG_E("read id fail id:0x%08x", id);
- return RT_ERROR;
- }
- pdat = rt_malloc(sizeof(struct keyboard_pl050_pdata_t));
- if(!pdat)
- {
- LOG_E("malloc memory failed");
- return RT_ERROR;
- }
- rt_memset(pdat, 0, sizeof(struct keyboard_pl050_pdata_t));
- pdat->virt = virt;
- pdat->irq = irq;
- write8(pdat->virt + KEYBOARD_CLKDIV, 0);
- write8(pdat->virt + KEYBOARD_CR, (1 << 2));
- kmi_read(pdat, &value);
- kmi_write(pdat, 0xff);
- kmi_read(pdat, &value);
- kmi_write(pdat, 0xf3);
- kmi_write(pdat, 0x2b);
- kmi_write(pdat, 0xf0);
- kmi_write(pdat, 0x02);
- kmi_write(pdat, 0xfa);
- kmi_write(pdat, 0xed);
- kmi_write(pdat, 0x02);
- write8(pdat->virt + KEYBOARD_CR, (1 << 2) | (1 << 4));
- rt_hw_interrupt_install(irq, keyboard_pl050_interrupt, (void *)pdat, "keyboard");
- rt_hw_interrupt_umask(irq);
- return RT_EOK;
- }
- INIT_DEVICE_EXPORT(rt_hw_keyboard_init);
- #endif
|