summaryrefslogtreecommitdiff
path: root/bsp
diff options
context:
space:
mode:
authortangyuxin <[email protected]>2017-12-31 16:21:45 +0800
committertangyuxin <[email protected]>2017-12-31 16:22:43 +0800
commite36a989f25014b4118f01bc2bdbad96f54868d23 (patch)
tree7e008e11456cbb815ba4e7fa7dce57d0208ebe23 /bsp
parent1f25504c0b37f329ecbcd81472fb435ba591574b (diff)
[bsp]qemu-vexpress-a9添加鼠标键盘驱动
Diffstat (limited to 'bsp')
-rw-r--r--bsp/qemu-vexpress-a9/drivers/drv_keyboard.c474
-rw-r--r--bsp/qemu-vexpress-a9/drivers/drv_keyboard.h6
-rw-r--r--bsp/qemu-vexpress-a9/drivers/drv_mouse.c298
-rw-r--r--bsp/qemu-vexpress-a9/drivers/drv_mouse.h6
4 files changed, 784 insertions, 0 deletions
diff --git a/bsp/qemu-vexpress-a9/drivers/drv_keyboard.c b/bsp/qemu-vexpress-a9/drivers/drv_keyboard.c
new file mode 100644
index 0000000000..c0d139aaba
--- /dev/null
+++ b/bsp/qemu-vexpress-a9/drivers/drv_keyboard.c
@@ -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
diff --git a/bsp/qemu-vexpress-a9/drivers/drv_keyboard.h b/bsp/qemu-vexpress-a9/drivers/drv_keyboard.h
new file mode 100644
index 0000000000..6d5acb7427
--- /dev/null
+++ b/bsp/qemu-vexpress-a9/drivers/drv_keyboard.h
@@ -0,0 +1,6 @@
+#ifndef __DEV_KEYBOARD_H__
+#define __DEV_KEYBOARD_H__
+
+int rt_hw_keyboard_init(void);
+
+#endif
diff --git a/bsp/qemu-vexpress-a9/drivers/drv_mouse.c b/bsp/qemu-vexpress-a9/drivers/drv_mouse.c
new file mode 100644
index 0000000000..3b9b5fd774
--- /dev/null
+++ b/bsp/qemu-vexpress-a9/drivers/drv_mouse.c
@@ -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
diff --git a/bsp/qemu-vexpress-a9/drivers/drv_mouse.h b/bsp/qemu-vexpress-a9/drivers/drv_mouse.h
new file mode 100644
index 0000000000..c5d190950a
--- /dev/null
+++ b/bsp/qemu-vexpress-a9/drivers/drv_mouse.h
@@ -0,0 +1,6 @@
+#ifndef __DRV_MOUSE_H__
+#define __DRV_MOUSE_H__
+
+int rt_hw_mouse_init(void);
+
+#endif \ No newline at end of file