qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 17/18] hw: add QEMU model for Faraday a369 keypad co


From: Dante
Subject: [Qemu-devel] [PATCH 17/18] hw: add QEMU model for Faraday a369 keypad controller
Date: Fri, 18 Jan 2013 14:33:00 +0800

Signed-off-by: Kuo-Jung Su <address@hidden>
---
 hw/ftkbc010.c |  214 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 214 insertions(+)
 create mode 100644 hw/ftkbc010.c

diff --git a/hw/ftkbc010.c b/hw/ftkbc010.c
new file mode 100644
index 0000000..0727b5a
--- /dev/null
+++ b/hw/ftkbc010.c
@@ -0,0 +1,214 @@
+/*
+ * Faraday FTKBC010 emulator for A369.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ *
+ * Written by Dante Su <address@hidden>
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "sysbus.h"
+#include "ui/console.h"
+#include "devices.h"
+
+/* Key codes */
+#define KEYCODE_ESC                1
+#define KEYCODE_BACKSPACE        14
+#define KEYCODE_ENTER            28
+#define KEYCODE_SPACE            57
+#define KEYCODE_MENU            139    /* Menu (show menu) */
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq;
+
+    int x;
+    int y;
+    
+    /* HW registers */
+    uint32_t cr;
+    uint32_t isr;
+} ftkbc010_state;
+
+static inline void ftkbc010_update(void *opaque)
+{
+    ftkbc010_state *s = (ftkbc010_state *) opaque;
+    uint32_t ier = 0;
+    
+    /* keypad interrupt */
+    ier |= (s->cr & (1 << 8)) ? (1 << 2) : 0;
+    /* tx interrupt */
+    ier |= (s->cr & (1 << 3)) ? (1 << 1) : 0;
+    /* rx interrupt */
+    ier |= (s->cr & (1 << 4)) ? (1 << 0) : 0;
+    
+    if (ier & s->isr)
+        qemu_irq_raise(s->irq);
+    else
+        qemu_irq_lower(s->irq);
+}
+
+static uint64_t ftkbc010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+    ftkbc010_state *s = (ftkbc010_state *) opaque;
+
+    switch (addr) {
+    case 0x00:
+        return s->cr;
+    case 0x10:
+        return s->isr;
+    case 0x30:
+        return ~(1 << s->x);
+    case 0x34:
+        return ~(1 << s->y);
+    case 0x50:    /* revision */
+        return 0x00010403;
+    case 0x54:    /* feature */
+        return 0x00000808;
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+static void ftkbc010_mem_write(void *opaque, hwaddr addr, uint64_t val, 
unsigned size)
+{
+    ftkbc010_state *s = (ftkbc010_state *) opaque;
+
+    switch (addr) {
+    case 0x00:
+        s->cr = (uint32_t)val;
+        /* if ftkbc010 enabled */
+        if (!(s->cr & (1 << 2)))
+            break;
+        /* if keypad interrupt cleared */
+        if (s->cr & (1 << 10)) {
+            s->cr &= ~(1 << 10);
+            s->isr &= ~(1 << 2);
+        }
+        /* if rx interrupt cleared */
+        if (s->cr & (1 << 7)) {
+            s->cr &= ~(1 << 7);
+            s->isr &= ~(1 << 0);
+        }
+        /* if tx interrupt cleared */
+        if (s->cr & (1 << 6)) {
+            s->cr &= ~(1 << 6);
+            s->isr &= ~(1 << 1);
+        }
+        ftkbc010_update(s);
+        break;
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps ftkbc010_mem_ops = {
+    .read  = ftkbc010_mem_read,
+    .write = ftkbc010_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void ftkbc010_key_event(void *opaque, int scancode)
+{
+    ftkbc010_state *s = (ftkbc010_state *) opaque;
+    int released = 0;
+    
+    /* key release from qemu */
+    if (scancode & 0x80)
+        released = 1;
+
+    /* strip qemu key release bit */
+    scancode &= ~0x80;
+
+    /* keypad interrupt */
+    if (!released && (s->cr & (1 << 8))) {
+        switch(scancode) {
+        case KEYCODE_ESC:
+        case KEYCODE_BACKSPACE:
+            s->x = 1;
+            break;
+        case KEYCODE_ENTER:
+        case KEYCODE_MENU:
+        case KEYCODE_SPACE:
+            s->x = 3;
+            break;
+        default:
+            s->x = 2;    /* KEY_HOME */
+            break;
+        }
+        s->y = 0;
+        s->isr |= (1 << 2);
+        ftkbc010_update(s);
+    }
+}
+
+static int ftkbc010_post_load(void *opaque, int version_id)
+{
+    ftkbc010_state *s = (ftkbc010_state *) opaque;
+
+    qemu_irq_lower(s->irq);
+
+    return 0;
+}
+
+static int ftkbc010_init(SysBusDevice *dev)
+{
+    ftkbc010_state *s = FROM_SYSBUS(ftkbc010_state, dev);
+
+    s->cr  = 0;
+    s->isr = 0;
+    s->x   = 0;
+    s->y   = 0;
+
+    memory_region_init_io(&s->iomem, &ftkbc010_mem_ops, s, "ftkbc010", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+
+    qemu_add_kbd_event_handler(ftkbc010_key_event, s);
+    
+    return 0;
+}
+
+static const VMStateDescription vmstate_ftkbc010_regs = {
+    .name = "ftkbc010",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = ftkbc010_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(cr, ftkbc010_state),
+        VMSTATE_UINT32(isr, ftkbc010_state),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void ftkbc010_dev_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = ftkbc010_init;
+    dc->desc = "ftkbc010";
+    dc->vmsd  = &vmstate_ftkbc010_regs;
+}
+
+static TypeInfo ftkbc010_dev_info = {
+    .name          = "ftkbc010",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(ftkbc010_state),
+    .class_init    = ftkbc010_dev_class_init,
+};
+
+static void ftkbc010_register_types(void)
+{
+    type_register_static(&ftkbc010_dev_info);
+}
+
+type_init(ftkbc010_register_types)
-- 
1.7.9.5


********************* Confidentiality Notice ************************
This electronic message and any attachments may contain
confidential and legally privileged information or
information which is otherwise protected from disclosure.
If you are not the intended recipient,please do not disclose
the contents, either in whole or in part, to anyone,and
immediately delete the message and any attachments from
your computer system and destroy all hard copies.
Thank you for your cooperation.
***********************************************************************




reply via email to

[Prev in Thread] Current Thread [Next in Thread]