Merge pull request #1151 from enkiller/development
[bsp] Add keyboard and mouse driver for qemu-vexpress-a9
This commit is contained in:
commit
8a923193ab
|
@ -0,0 +1,474 @@
|
||||||
|
#include <rthw.h>
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <rtdevice.h>
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "interrupt.h"
|
||||||
|
#include "drv_keyboard.h"
|
||||||
|
|
||||||
|
#define DBG_LEVEL DBG_LOG
|
||||||
|
// #define DBG_ENABLE
|
||||||
|
#define DBG_COLOR
|
||||||
|
|
||||||
|
#include "rtdbg.h"
|
||||||
|
|
||||||
|
#define KEYBOARD_ADDRESS (0x10006000)
|
||||||
|
#define KEYBOARD_IRQ_NUM (IRQ_VEXPRESS_A9_KBD)
|
||||||
|
|
||||||
|
#ifdef RT_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)
|
||||||
|
{
|
||||||
|
dbg_log(DBG_LOG,"KEY info:\n");
|
||||||
|
if (flag & KBD_CAPS_LOCK)
|
||||||
|
{
|
||||||
|
dbg_log(DBG_LOG,"CAPS:LOCK\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dbg_log(DBG_LOG,"CAPS:UNLOCK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag & KBD_LEFT_SHIFT)
|
||||||
|
{
|
||||||
|
mod |= RTGUI_KMOD_LSHIFT;
|
||||||
|
dbg_log(DBG_LOG,"SHIFT:LEFT\n");
|
||||||
|
}
|
||||||
|
else if (flag & KBD_RIGHT_SHIFT)
|
||||||
|
{
|
||||||
|
mod |= RTGUI_KMOD_RSHIFT;
|
||||||
|
dbg_log(DBG_LOG,"SHIFT:RIGHT\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dbg_log(DBG_LOG,"SHIFT:NULL\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag & KBD_LEFT_CTRL)
|
||||||
|
{
|
||||||
|
mod |= RTGUI_KMOD_LCTRL;
|
||||||
|
dbg_log(DBG_LOG,"CTRL:LEFT\n");
|
||||||
|
}
|
||||||
|
else if (flag & KBD_RIGHT_CTRL)
|
||||||
|
{
|
||||||
|
mod |= RTGUI_KMOD_RCTRL;
|
||||||
|
dbg_log(DBG_LOG,"CTRL:RIGHT\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dbg_log(DBG_LOG,"CTRL:NULL\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg_log(DBG_LOG,"flag:0x%08x value:0x%x key:%s status:%s\n", \
|
||||||
|
flag, data, map[i].normal_key, press ==0 ? "UP" : "DOWN");
|
||||||
|
find_key = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (find_key == 0)
|
||||||
|
{
|
||||||
|
dbg_log(DBG_LOG,"flag:0x%08x value:0x%x key:%s status:%s\n", \
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
dbg_log(DBG_ERROR, "read id fail id:0x%08x\n", id);
|
||||||
|
return RT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdat = rt_malloc(sizeof(struct keyboard_pl050_pdata_t));
|
||||||
|
if(!pdat)
|
||||||
|
{
|
||||||
|
dbg_log(DBG_ERROR, "malloc memory\n", id);
|
||||||
|
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
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef __DEV_KEYBOARD_H__
|
||||||
|
#define __DEV_KEYBOARD_H__
|
||||||
|
|
||||||
|
int rt_hw_keyboard_init(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,298 @@
|
||||||
|
#include <rthw.h>
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <rtdevice.h>
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "interrupt.h"
|
||||||
|
#include "drv_mouse.h"
|
||||||
|
|
||||||
|
#define DBG_LEVEL DBG_LOG
|
||||||
|
// #define DBG_ENABLE
|
||||||
|
#define DBG_COLOR
|
||||||
|
|
||||||
|
#include "rtdbg.h"
|
||||||
|
|
||||||
|
#define MOUSE_ADDRESS (0x10007000)
|
||||||
|
#define MOUSE_IRQ_NUM (IRQ_VEXPRESS_A9_MOUSE)
|
||||||
|
#define MOUSE_XMAX (800)
|
||||||
|
#define MOUSE_YMAX (480)
|
||||||
|
|
||||||
|
#define MOUSE_BUTTON_LEFT (0x01)
|
||||||
|
#define MOUSE_BUTTON_RIGHT (0x02)
|
||||||
|
#define MOUSE_BUTTON_MIDDLE (0x04)
|
||||||
|
#define MOUSE_BUTTON_DOWN (0x10)
|
||||||
|
#define MOUSE_BUTTON_UP (0x20)
|
||||||
|
#define MOUSE_BUTTON_MOVE (0x40)
|
||||||
|
#define MOUSE_BUTTON_WHELL (0x80)
|
||||||
|
|
||||||
|
#ifdef RT_USING_GUIENGINE
|
||||||
|
|
||||||
|
#include <rtgui/event.h>
|
||||||
|
#include <rtgui/rtgui_server.h>
|
||||||
|
|
||||||
|
typedef rt_uint32_t virtual_addr_t;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MOUSE_CR = 0x00,
|
||||||
|
MOUSE_STAT = 0x04,
|
||||||
|
MOUSE_DATA = 0x08,
|
||||||
|
MOUSE_CLKDIV = 0x0c,
|
||||||
|
MOUSE_IIR = 0x10,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mouse_pl050_pdata_t {
|
||||||
|
virtual_addr_t virt;
|
||||||
|
int irq;
|
||||||
|
int xmax, ymax;
|
||||||
|
int xpos, ypos;
|
||||||
|
unsigned char packet[4];
|
||||||
|
int index;
|
||||||
|
int obtn;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 mouse_pl050_pdata_t * pdat, rt_uint8_t value)
|
||||||
|
{
|
||||||
|
int timeout = 1000;
|
||||||
|
|
||||||
|
while((read8(pdat->virt + MOUSE_STAT) & (1 << 6)) == 0 && timeout--);
|
||||||
|
|
||||||
|
if(timeout)
|
||||||
|
{
|
||||||
|
write8(pdat->virt + MOUSE_DATA, value);
|
||||||
|
while((read8(pdat->virt + MOUSE_STAT) & (1 << 4)) == 0);
|
||||||
|
|
||||||
|
if(read8(pdat->virt + MOUSE_DATA) == 0xfa)
|
||||||
|
return RT_TRUE;
|
||||||
|
}
|
||||||
|
return RT_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_inline int kmi_read(struct mouse_pl050_pdata_t * pdat, rt_uint8_t * value)
|
||||||
|
{
|
||||||
|
if((read8(pdat->virt + MOUSE_STAT) & (1 << 4)))
|
||||||
|
{
|
||||||
|
*value = read8(pdat->virt + MOUSE_DATA);
|
||||||
|
return RT_TRUE;
|
||||||
|
}
|
||||||
|
return RT_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_uint32_t emouse_id;
|
||||||
|
|
||||||
|
void push_event_touch_move(int x, int y)
|
||||||
|
{
|
||||||
|
struct rtgui_event_mouse emouse;
|
||||||
|
|
||||||
|
emouse.parent.sender = RT_NULL;
|
||||||
|
emouse.wid = RT_NULL;
|
||||||
|
|
||||||
|
emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN;
|
||||||
|
emouse.parent.type = RTGUI_EVENT_MOUSE_MOTION;
|
||||||
|
emouse.x = x;
|
||||||
|
emouse.y = y;
|
||||||
|
emouse.ts = rt_tick_get();
|
||||||
|
emouse.id = emouse_id;
|
||||||
|
|
||||||
|
dbg_log(DBG_LOG, "[line]:%d motion event id:%d x:%d y:%d\n", __LINE__, emouse.id, x, y);
|
||||||
|
rtgui_server_post_event(&emouse.parent, sizeof(emouse));
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_event_touch_begin(int x, int y)
|
||||||
|
{
|
||||||
|
struct rtgui_event_mouse emouse;
|
||||||
|
|
||||||
|
emouse_id = rt_tick_get();
|
||||||
|
|
||||||
|
emouse.parent.sender = RT_NULL;
|
||||||
|
emouse.wid = RT_NULL;
|
||||||
|
|
||||||
|
emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
|
||||||
|
emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN;
|
||||||
|
emouse.x = x;
|
||||||
|
emouse.y = y;
|
||||||
|
emouse.ts = rt_tick_get();
|
||||||
|
emouse.id = emouse_id;
|
||||||
|
dbg_log(DBG_LOG, "[line]:%d down event id:%d x:%d y:%d\n", __LINE__, emouse.id, x, y);
|
||||||
|
rtgui_server_post_event(&emouse.parent, sizeof(emouse));
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_event_touch_end(int x, int y)
|
||||||
|
{
|
||||||
|
struct rtgui_event_mouse emouse;
|
||||||
|
|
||||||
|
emouse.parent.sender = RT_NULL;
|
||||||
|
emouse.wid = RT_NULL;
|
||||||
|
|
||||||
|
emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
|
||||||
|
emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_UP;
|
||||||
|
emouse.x = x;
|
||||||
|
emouse.y = y;
|
||||||
|
emouse.ts = rt_tick_get();
|
||||||
|
emouse.id = emouse_id;
|
||||||
|
|
||||||
|
dbg_log(DBG_LOG, "[line]:%d up event id:%d x:%d y:%d\n", __LINE__, emouse.id, x, y);
|
||||||
|
rtgui_server_post_event(&emouse.parent, sizeof(emouse));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mouse_pl050_interrupt(int irq, void * data)
|
||||||
|
{
|
||||||
|
struct mouse_pl050_pdata_t * pdat = (struct mouse_pl050_pdata_t *)data;
|
||||||
|
int x, y, relx, rely, delta;
|
||||||
|
int btndown, btnup, btn;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
status = read8(pdat->virt + MOUSE_IIR);
|
||||||
|
while(status & (1 << 0))
|
||||||
|
{
|
||||||
|
pdat->packet[pdat->index] = read8(pdat->virt + MOUSE_DATA);
|
||||||
|
pdat->index = (pdat->index + 1) & 0x3;
|
||||||
|
|
||||||
|
if(pdat->index == 0)
|
||||||
|
{
|
||||||
|
btn = pdat->packet[0] & 0x7;
|
||||||
|
btndown = (btn ^ pdat->obtn) & btn;
|
||||||
|
btnup = (btn ^ pdat->obtn) & pdat->obtn;
|
||||||
|
pdat->obtn = btn;
|
||||||
|
|
||||||
|
if(pdat->packet[0] & 0x10)
|
||||||
|
relx = 0xffffff00 | pdat->packet[1];
|
||||||
|
else
|
||||||
|
relx = pdat->packet[1];
|
||||||
|
|
||||||
|
if(pdat->packet[0] & 0x20)
|
||||||
|
rely = 0xffffff00 | pdat->packet[2];
|
||||||
|
else
|
||||||
|
rely = pdat->packet[2];
|
||||||
|
rely = -rely;
|
||||||
|
|
||||||
|
delta = pdat->packet[3] & 0xf;
|
||||||
|
if(delta == 0xf)
|
||||||
|
delta = -1;
|
||||||
|
|
||||||
|
if(relx != 0)
|
||||||
|
{
|
||||||
|
pdat->xpos = pdat->xpos + relx;
|
||||||
|
if(pdat->xpos < 0)
|
||||||
|
pdat->xpos = 0;
|
||||||
|
if(pdat->xpos > pdat->xmax - 1)
|
||||||
|
pdat->xpos = pdat->xmax - 1;
|
||||||
|
}
|
||||||
|
if(rely != 0)
|
||||||
|
{
|
||||||
|
pdat->ypos = pdat->ypos + rely;
|
||||||
|
if(pdat->ypos < 0)
|
||||||
|
pdat->ypos = 0;
|
||||||
|
if(pdat->ypos > pdat->ymax - 1)
|
||||||
|
pdat->ypos = pdat->ymax - 1;
|
||||||
|
}
|
||||||
|
x = pdat->xpos;
|
||||||
|
y = pdat->ypos;
|
||||||
|
|
||||||
|
if((btn & (0x01 << 0)) && ((relx != 0) || (rely != 0)))
|
||||||
|
push_event_touch_move(x, y);
|
||||||
|
|
||||||
|
if(btndown & (0x01 << 0))
|
||||||
|
push_event_touch_begin(x, y);
|
||||||
|
|
||||||
|
if(btnup & (0x01 << 0))
|
||||||
|
push_event_touch_end(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = read8(pdat->virt + MOUSE_IIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rt_hw_mouse_init(void)
|
||||||
|
{
|
||||||
|
rt_uint8_t value;
|
||||||
|
rt_uint32_t id;
|
||||||
|
struct mouse_pl050_pdata_t *pdat;
|
||||||
|
virtual_addr_t virt = MOUSE_ADDRESS;
|
||||||
|
int irq = MOUSE_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)
|
||||||
|
{
|
||||||
|
dbg_log(DBG_ERROR, "read id fail id:0x%08x\n", id);
|
||||||
|
return RT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdat = rt_malloc(sizeof(struct mouse_pl050_pdata_t));
|
||||||
|
if(!pdat)
|
||||||
|
{
|
||||||
|
dbg_log(DBG_ERROR, "malloc memory\n", id);
|
||||||
|
return RT_ERROR;
|
||||||
|
}
|
||||||
|
rt_memset(pdat, 0, sizeof(struct mouse_pl050_pdata_t));
|
||||||
|
|
||||||
|
pdat->virt = virt;
|
||||||
|
pdat->irq = irq;
|
||||||
|
pdat->xmax = MOUSE_XMAX;
|
||||||
|
pdat->ymax = MOUSE_YMAX;
|
||||||
|
pdat->xpos = pdat->xmax / 2;
|
||||||
|
pdat->ypos = pdat->ymax / 2;
|
||||||
|
pdat->packet[0] = 0;
|
||||||
|
pdat->packet[1] = 0;
|
||||||
|
pdat->packet[2] = 0;
|
||||||
|
pdat->packet[3] = 0;
|
||||||
|
pdat->index = 0;
|
||||||
|
pdat->obtn = 0;
|
||||||
|
|
||||||
|
write8(pdat->virt + MOUSE_CLKDIV, 0);
|
||||||
|
write8(pdat->virt + MOUSE_CR, (1 << 2));
|
||||||
|
kmi_write(pdat, 0xff);
|
||||||
|
kmi_read(pdat, &value);
|
||||||
|
kmi_write(pdat, 0xf3);
|
||||||
|
kmi_write(pdat, 200);
|
||||||
|
kmi_write(pdat, 0xf3);
|
||||||
|
kmi_write(pdat, 100);
|
||||||
|
kmi_write(pdat, 0xf3);
|
||||||
|
kmi_write(pdat, 80);
|
||||||
|
kmi_write(pdat, 0xf2);
|
||||||
|
kmi_read(pdat, &value);
|
||||||
|
kmi_read(pdat, &value);
|
||||||
|
kmi_write(pdat, 0xf3);
|
||||||
|
kmi_write(pdat, 100);
|
||||||
|
kmi_write(pdat, 0xe8);
|
||||||
|
kmi_write(pdat, 0x02);
|
||||||
|
kmi_write(pdat, 0xe6);
|
||||||
|
kmi_write(pdat, 0xf4);
|
||||||
|
kmi_read(pdat, &value);
|
||||||
|
kmi_read(pdat, &value);
|
||||||
|
kmi_read(pdat, &value);
|
||||||
|
kmi_read(pdat, &value);
|
||||||
|
write8(pdat->virt + MOUSE_CR, (1 << 2) | (1 << 4));
|
||||||
|
|
||||||
|
rt_hw_interrupt_install(pdat->irq, mouse_pl050_interrupt, (void *)pdat, "mouse");
|
||||||
|
rt_hw_interrupt_umask(pdat->irq);
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
INIT_DEVICE_EXPORT(rt_hw_mouse_init);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef __DRV_MOUSE_H__
|
||||||
|
#define __DRV_MOUSE_H__
|
||||||
|
|
||||||
|
int rt_hw_mouse_init(void);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue