18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
120e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner#include "hw/android/goldfish/device.h"
1328a09b6fe8d8f3e92ffee9263609a6da881b8818David 'Digit' Turner#include "migration/qemu-file.h"
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/hw-events.h"
15b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project#include "android/charmap.h"
16b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project#include "android/globals.h"  /* for android_hw */
178dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine#include "android/multitouch-screen.h"
189b3a4b03315af9bcdf282243059e8fd1ce1c5c70David 'Digit' Turner#include "exec/cpu-common.h"
199b3a4b03315af9bcdf282243059e8fd1ce1c5c70David 'Digit' Turner#include "exec/hwaddr.h"
200e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner#include "hw/hw.h"
212ec695af7284adbedcdbc08a22d818b6bdd8990cDavid 'Digit' Turner#include "hw/irq.h"
22d4e803c5e928790b14704ae7f0b048da7ba47fabDavid 'Digit' Turner#include "android/user-events.h"
231c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "ui/console.h"
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MAX_EVENTS 256*4
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectenum {
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    REG_READ        = 0x00,
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    REG_SET_PAGE    = 0x00,
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    REG_LEN         = 0x04,
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    REG_DATA        = 0x08,
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PAGE_NAME       = 0x00000,
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PAGE_EVBITS     = 0x10000,
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PAGE_ABSDATA    = 0x20000 | EV_ABS,
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3880bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner/* These corresponds to the state of the driver.
3980bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner * Unfortunately, we have to buffer events coming
4080bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner * from the UI, since the kernel driver is not
4180bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner * capable of receiving them until XXXXXX
4280bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner */
4380bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turnerenum {
4480bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    STATE_INIT = 0,  /* The device is initialized */
4580bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    STATE_BUFFERED,  /* Events have been buffered, but no IRQ raised yet */
4680bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    STATE_LIVE       /* Events can be sent directly to the kernel */
4780bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner};
4880bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner
49b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project/* NOTE: The ev_bits arrays are used to indicate to the kernel
50b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project *       which events can be sent by the emulated hardware.
51b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project */
52b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t base;
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_irq  irq;
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pending;
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int page;
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned events[MAX_EVENTS];
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned first;
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned last;
6380bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    unsigned state;
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *name;
66b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct {
68b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        size_t   len;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint8_t *bits;
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } ev_bits[EV_MAX + 1];
71b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int32_t *abs_info;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size_t abs_info_count;
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} events_state;
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
768dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine/* An entry in the array of ABS_XXX values */
778dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkinetypedef struct ABSEntry {
788dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine    /* Minimum ABS_XXX value. */
798dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine    uint32_t    min;
808dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine    /* Maximum ABS_XXX value. */
818dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine    uint32_t    max;
828dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine    /* 'fuzz;, and 'flat' ABS_XXX values are always zero here. */
838dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine    uint32_t    fuzz;
848dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine    uint32_t    flat;
858dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine} ABSEntry;
868dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine
878dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* modify this each time you change the events_device structure. you
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * will also need to upadte events_state_load and events_state_save
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
9180bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner#define  EVENTS_STATE_SAVE_VERSION  2
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef  QFIELD_STRUCT
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define QFIELD_STRUCT  events_state
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectQFIELD_BEGIN(events_state_fields)
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QFIELD_INT32(pending),
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QFIELD_INT32(page),
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QFIELD_BUFFER(events),
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QFIELD_INT32(first),
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QFIELD_INT32(last),
10280bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    QFIELD_INT32(state),
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectQFIELD_END
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void  events_state_save(QEMUFile*  f, void*  opaque)
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    events_state*  s = opaque;
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_put_struct(f, events_state_fields, s);
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int  events_state_load(QEMUFile*  f, void* opaque, int  version_id)
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    events_state*  s = opaque;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (version_id != EVENTS_STATE_SAVE_VERSION)
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return qemu_get_struct(f, events_state_fields, s);
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void enqueue_event(events_state *s, unsigned int type, unsigned int code, int value)
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  enqueued = s->last - s->first;
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (enqueued < 0)
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        enqueued += MAX_EVENTS;
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12980bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    if (enqueued + 3 > MAX_EVENTS) {
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fprintf(stderr, "##KBD: Full queue, lose event\n");
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
134055ae42d36d9d78a7920f66ee2df485d81d24264David 'Digit' Turner    if(s->first == s->last) {
13580bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner	if (s->state == STATE_LIVE)
13680bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner	  qemu_irq_raise(s->irq);
13780bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner	else {
13880bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner	  s->state = STATE_BUFFERED;
13980bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner	}
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    //fprintf(stderr, "##KBD: type=%d code=%d value=%d\n", type, code, value);
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->events[s->last] = type;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->last = (s->last + 1) & (MAX_EVENTS-1);
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->events[s->last] = code;
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->last = (s->last + 1) & (MAX_EVENTS-1);
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->events[s->last] = value;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->last = (s->last + 1) & (MAX_EVENTS-1);
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic unsigned dequeue_event(events_state *s)
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned n;
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if(s->first == s->last) {
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    n = s->events[s->first];
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->first = (s->first + 1) & (MAX_EVENTS - 1);
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if(s->first == s->last) {
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_irq_lower(s->irq);
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
167334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima#ifdef TARGET_I386
168334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima    /*
169334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima     * Adding the logic to handle edge-triggered interrupts for x86
170334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima     * because the exisiting goldfish events device basically provides
171334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima     * level-trigger interrupts only.
172334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima     *
173334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima     * Logic: When an event (including the type/code/value) is fetched
174334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima     * by the driver, if there is still another event in the event
175334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima     * queue, the goldfish event device will re-assert the IRQ so that
176334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima     * the driver can be notified to fetch the event again.
177334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima     */
178334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima    else if (((s->first + 2) & (MAX_EVENTS - 1)) < s->last ||
179334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima               (s->first & (MAX_EVENTS - 1)) > s->last) { /* if there still is an event */
180334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima        qemu_irq_lower(s->irq);
181334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima        qemu_irq_raise(s->irq);
182334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima    }
183334ab475d2f27dbf6fbf836c2d4fb86dbb02a15cJun Nakajima#endif
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return n;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int get_page_len(events_state *s)
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int page = s->page;
1900158ea3220978ecc0fa1738e4a0bdae83fa36175David 'Digit' Turner    if (page == PAGE_NAME) {
19172d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet        const char* name = s->name;
1920158ea3220978ecc0fa1738e4a0bdae83fa36175David 'Digit' Turner        return strlen(name);
1930158ea3220978ecc0fa1738e4a0bdae83fa36175David 'Digit' Turner    } if (page >= PAGE_EVBITS && page <= PAGE_EVBITS + EV_MAX)
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return s->ev_bits[page - PAGE_EVBITS].len;
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (page == PAGE_ABSDATA)
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return s->abs_info_count * sizeof(s->abs_info[0]);
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int get_page_data(events_state *s, int offset)
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int page_len = get_page_len(s);
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int page = s->page;
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (offset > page_len)
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
2060158ea3220978ecc0fa1738e4a0bdae83fa36175David 'Digit' Turner    if (page == PAGE_NAME) {
20772d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet        const char* name = s->name;
2080158ea3220978ecc0fa1738e4a0bdae83fa36175David 'Digit' Turner        return name[offset];
2090158ea3220978ecc0fa1738e4a0bdae83fa36175David 'Digit' Turner    } if (page >= PAGE_EVBITS && page <= PAGE_EVBITS + EV_MAX)
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return s->ev_bits[page - PAGE_EVBITS].bits[offset];
21180bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    if (page == PAGE_ABSDATA) {
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return s->abs_info[offset / sizeof(s->abs_info[0])];
21380bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    }
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
217bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t events_read(void *x, hwaddr off)
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    events_state *s = (events_state *) x;
2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int offset = off; // - s->base;
22180bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner
22280bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    /* This gross hack below is used to ensure that we
22380bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner     * only raise the IRQ when the kernel driver is
22480bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner     * properly ready! If done before this, the driver
22580bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner     * becomes confused and ignores all input events
22680bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner     * as soon as one was buffered!
22780bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner     */
22880bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    if (offset == REG_LEN && s->page == PAGE_ABSDATA) {
22980bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner	if (s->state == STATE_BUFFERED)
23080bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner	  qemu_irq_raise(s->irq);
23180bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner	s->state = STATE_LIVE;
23280bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    }
23380bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (offset == REG_READ)
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return dequeue_event(s);
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if (offset == REG_LEN)
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return get_page_len(s);
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if (offset >= REG_DATA)
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return get_page_data(s, offset - REG_DATA);
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0; // this shouldn't happen, if the driver does the right thing
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
243bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void events_write(void *x, hwaddr off, uint32_t val)
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    events_state *s = (events_state *) x;
2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int offset = off; // - s->base;
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (offset == REG_SET_PAGE)
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->page = val;
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CPUReadMemoryFunc *events_readfn[] = {
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   events_read,
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   events_read,
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   events_read
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CPUWriteMemoryFunc *events_writefn[] = {
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   events_write,
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   events_write,
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   events_write
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void events_put_keycode(void *x, int keycode)
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    events_state *s = (events_state *) x;
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    enqueue_event(s, EV_KEY, keycode&0x1ff, (keycode&0x200) ? 1 : 0);
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void events_put_mouse(void *opaque, int dx, int dy, int dz, int buttons_state)
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    events_state *s = (events_state *) opaque;
273b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    /* in the Android emulator, we use dz == 0 for touchscreen events,
274b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * and dz == 1 for trackball events. See the kbd_mouse_event calls
275b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * in android/skin/trackball.c and android/skin/window.c
276b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     */
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dz == 0) {
278863d1010d9c8fa4342b1b0ea860bcfb096806accVladimir Chtchetkine        if (androidHwConfig_isScreenMultiTouch(android_hw)) {
2798dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            /* Convert mouse event into multi-touch event */
2808dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            multitouch_update_pointer(MTES_MOUSE, 0, dx, dy,
2818dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine                                      (buttons_state & 1) ? 0x81 : 0);
282863d1010d9c8fa4342b1b0ea860bcfb096806accVladimir Chtchetkine        } else if (androidHwConfig_isScreenTouch(android_hw)) {
2838dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            enqueue_event(s, EV_ABS, ABS_X, dx);
2848dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            enqueue_event(s, EV_ABS, ABS_Y, dy);
2858dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            enqueue_event(s, EV_ABS, ABS_Z, dz);
2868dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            enqueue_event(s, EV_KEY, BTN_TOUCH, buttons_state&1);
2878dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            enqueue_event(s, EV_SYN, 0, 0);
2888dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        }
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        enqueue_event(s, EV_REL, REL_X, dx);
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        enqueue_event(s, EV_REL, REL_Y, dy);
2928dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        enqueue_event(s, EV_SYN, 0, 0);
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void  events_put_generic(void*  opaque, int  type, int  code, int  value)
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2988dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine    events_state *s = (events_state *) opaque;
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    enqueue_event(s, type, code, value);
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
303b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project/* set bits [bitl..bith] in the ev_bits[type] array
304b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project */
305b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Projectstatic void
306b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Projectevents_set_bits(events_state *s, int type, int bitl, int bith)
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *bits;
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t maskl, maskh;
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int il, ih;
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    il = bitl / 8;
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ih = bith / 8;
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ih >= s->ev_bits[type].len) {
314aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        bits = g_malloc0(ih + 1);
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bits == NULL)
316b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project            return;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(bits, s->ev_bits[type].bits, s->ev_bits[type].len);
318aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        g_free(s->ev_bits[type].bits);
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->ev_bits[type].bits = bits;
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->ev_bits[type].len = ih + 1;
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits = s->ev_bits[type].bits;
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    maskl = 0xffU << (bitl & 7);
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    maskh = 0xffU >> (7 - (bith & 7));
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (il >= ih)
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        maskh &= maskl;
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits[il] |= maskl;
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (++il < ih)
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bits[il] = 0xff;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bits[ih] |= maskh;
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
336b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Projectstatic void
337b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Projectevents_set_bit(events_state* s, int  type, int  bit)
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
339b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bits(s, type, bit, bit);
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
342799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turnerstatic void
343799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turnerevents_clr_bit(events_state* s, int type, int bit)
344799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner{
345799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner    int ii = bit / 8;
346799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner    if (ii < s->ev_bits[type].len) {
347799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner        uint8_t* bits = s->ev_bits[type].bits;
348799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner        uint8_t  mask = 0x01U << (bit & 7);
349799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner        bits[ii] &= ~mask;
350799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner    }
351799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner}
352799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid events_dev_init(uint32_t base, qemu_irq irq)
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    events_state *s;
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int iomemtype;
357b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    AndroidHwConfig*  config = android_hw;
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
359aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    s = (events_state *) g_malloc0(sizeof(events_state));
3600158ea3220978ecc0fa1738e4a0bdae83fa36175David 'Digit' Turner
361b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    /* now set the events capability bits depending on hardware configuration */
362b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    /* apparently, the EV_SYN array is used to indicate which other
363b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * event classes to consider.
364b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     */
365b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
366b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    /* configure EV_KEY array
367b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *
368b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * All Android devices must have the following keys:
369b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *   KEY_HOME, KEY_BACK, KEY_SEND (Call), KEY_END (EndCall),
370b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *   KEY_SOFT1 (Menu), VOLUME_UP, VOLUME_DOWN
371b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *
372b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *   Note that previous models also had a KEY_SOFT2,
373b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *   and a KEY_POWER  which we still support here.
374b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *
3753d2300cb2f8f575d9e0c553c88790b5d79dda1b6David 'Digit' Turner     *   Newer models have a KEY_SEARCH key, which we always
3763d2300cb2f8f575d9e0c553c88790b5d79dda1b6David 'Digit' Turner     *   enable here.
3773d2300cb2f8f575d9e0c553c88790b5d79dda1b6David 'Digit' Turner     *
378b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * A Dpad will send: KEY_DOWN / UP / LEFT / RIGHT / CENTER
379b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *
380b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * The KEY_CAMERA button isn't very useful if there is no camera.
381b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *
382b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * BTN_MOUSE is sent when the trackball is pressed
383b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * BTN_TOUCH is sent when the touchscreen is pressed
384b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     */
385b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bit (s, EV_SYN, EV_KEY );
386b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
387b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bit(s, EV_KEY, KEY_HOME);
388b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bit(s, EV_KEY, KEY_BACK);
389b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bit(s, EV_KEY, KEY_SEND);
390b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bit(s, EV_KEY, KEY_END);
391b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bit(s, EV_KEY, KEY_SOFT1);
392b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bit(s, EV_KEY, KEY_VOLUMEUP);
393b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bit(s, EV_KEY, KEY_VOLUMEDOWN);
394b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bit(s, EV_KEY, KEY_SOFT2);
395b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    events_set_bit(s, EV_KEY, KEY_POWER);
3963d2300cb2f8f575d9e0c553c88790b5d79dda1b6David 'Digit' Turner    events_set_bit(s, EV_KEY, KEY_SEARCH);
397b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
398b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    if (config->hw_dPad) {
399b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit(s, EV_KEY, KEY_DOWN);
400b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit(s, EV_KEY, KEY_UP);
401b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit(s, EV_KEY, KEY_LEFT);
402b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit(s, EV_KEY, KEY_RIGHT);
403b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit(s, EV_KEY, KEY_CENTER);
404b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    }
405b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
406b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    if (config->hw_trackBall) {
407b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit(s, EV_KEY, BTN_MOUSE);
408b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    }
409863d1010d9c8fa4342b1b0ea860bcfb096806accVladimir Chtchetkine    if (androidHwConfig_isScreenTouch(config)) {
410b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit(s, EV_KEY, BTN_TOUCH);
411b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    }
412b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
4137485c2989d727a1d0c14a66fb75e140f885a1583Vladimir Chtchetkine    if (strcmp(config->hw_camera_back, "none") ||
4147485c2989d727a1d0c14a66fb75e140f885a1583Vladimir Chtchetkine        strcmp(config->hw_camera_front, "none")) {
4157485c2989d727a1d0c14a66fb75e140f885a1583Vladimir Chtchetkine        /* Camera emulation is enabled. */
416b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit(s, EV_KEY, KEY_CAMERA);
417b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    }
418b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
419b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    if (config->hw_keyboard) {
420b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        /* since we want to implement Unicode reverse-mapping
421b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project         * allow any kind of key, even those not available on
422b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project         * the skin.
423b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project         *
424b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project         * the previous code did set the [1..0x1ff] range, but
425b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project         * we don't want to enable certain bits in the middle
426b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project         * of the range that are registered for mouse/trackball/joystick
427b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project         * events.
428b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project         *
429b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project         * see "linux_keycodes.h" for the list of events codes.
430b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project         */
431b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bits(s, EV_KEY, 1, 0xff);
432b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bits(s, EV_KEY, 0x160, 0x1ff);
433799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner
434799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner        /* If there is a keyboard, but no DPad, we need to clear the
435799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner         * corresponding bits. Doing this is simpler than trying to exclude
436799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner         * the DPad values from the ranges above.
437799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner         */
438799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner        if (!config->hw_dPad) {
439799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner            events_clr_bit(s, EV_KEY, KEY_DOWN);
440799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner            events_clr_bit(s, EV_KEY, KEY_UP);
441799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner            events_clr_bit(s, EV_KEY, KEY_LEFT);
442799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner            events_clr_bit(s, EV_KEY, KEY_RIGHT);
443799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner            events_clr_bit(s, EV_KEY, KEY_CENTER);
444799c6c0ecab548cf4716d14d1f077819cdde8e10David 'Digit' Turner        }
445b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    }
446b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
447b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    /* configure EV_REL array
448b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *
449b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * EV_REL events are sent when the trackball is moved
450b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     */
451b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    if (config->hw_trackBall) {
452b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit (s, EV_SYN, EV_REL );
453b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bits(s, EV_REL, REL_X, REL_Y);
454b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    }
455b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
456b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    /* configure EV_ABS array.
457b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *
458b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * EV_ABS events are sent when the touchscreen is pressed
459b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     */
460863d1010d9c8fa4342b1b0ea860bcfb096806accVladimir Chtchetkine    if (!androidHwConfig_isScreenNoTouch(config)) {
4618dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        ABSEntry* abs_values;
46231203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet
463b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit (s, EV_SYN, EV_ABS );
464b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bits(s, EV_ABS, ABS_X, ABS_Z);
46531203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet        /* Allocate the absinfo to report the min/max bounds for each
4668dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine         * absolute dimension. The array must contain 3, or ABS_MAX tuples
46731203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet         * of (min,max,fuzz,flat) 32-bit values.
46831203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet         *
46931203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet         * min and max are the bounds
47031203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet         * fuzz corresponds to the device's fuziness, we set it to 0
47131203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet         * flat corresponds to the flat position for JOEYDEV devices,
47231203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet         * we also set it to 0.
47331203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet         *
47431203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet         * There is no need to save/restore this array in a snapshot
47531203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet         * since the values only depend on the hardware configuration.
47631203e4ba2e7b91aabe077aa9cac9158dd480775Xavier Ducrohet         */
477863d1010d9c8fa4342b1b0ea860bcfb096806accVladimir Chtchetkine        s->abs_info_count = androidHwConfig_isScreenMultiTouch(config) ? ABS_MAX * 4 : 3 * 4;
4788dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        const int abs_size = sizeof(uint32_t) * s->abs_info_count;
4798dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        s->abs_info = malloc(abs_size);
4808dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        memset(s->abs_info, 0, abs_size);
4818dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        abs_values = (ABSEntry*)s->abs_info;
4828dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine
4838dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        abs_values[ABS_X].max = config->hw_lcd_width-1;
4848dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        abs_values[ABS_Y].max = config->hw_lcd_height-1;
4858dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        abs_values[ABS_Z].max = 1;
4868dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine
487863d1010d9c8fa4342b1b0ea860bcfb096806accVladimir Chtchetkine        if (androidHwConfig_isScreenMultiTouch(config)) {
4888dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            /*
4898dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine             * Setup multitouch.
4908dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine             */
4918dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            events_set_bit(s, EV_ABS, ABS_MT_SLOT);
4928dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            events_set_bit(s, EV_ABS, ABS_MT_POSITION_X);
4938dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            events_set_bit(s, EV_ABS, ABS_MT_POSITION_Y);
4948dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            events_set_bit(s, EV_ABS, ABS_MT_TRACKING_ID);
4958dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            events_set_bit(s, EV_ABS, ABS_MT_TOUCH_MAJOR);
4968dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            events_set_bit(s, EV_ABS, ABS_MT_PRESSURE);
4978dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine
4988dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            abs_values[ABS_MT_SLOT].max = multitouch_get_max_slot();
4998dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            abs_values[ABS_MT_TRACKING_ID].max = abs_values[ABS_MT_SLOT].max + 1;
5008dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            abs_values[ABS_MT_POSITION_X].max = abs_values[ABS_X].max;
5018dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            abs_values[ABS_MT_POSITION_Y].max = abs_values[ABS_Y].max;
5028dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            abs_values[ABS_MT_TOUCH_MAJOR].max = 0x7fffffff; // TODO: Make it less random
5038dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine            abs_values[ABS_MT_PRESSURE].max = 0x100; // TODO: Make it less random
5048dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine        }
505b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    }
506b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
507b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    /* configure EV_SW array
508b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *
50971bc069784aa4e4e78a83f03d73622f3d4af6250SeongJae Park     * EV_SW events are sent to indicate that the keyboard lid
510b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * was closed or opened (done when we switch layouts through
511b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     * KP-7 or KP-9).
512b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     *
5138b9887163ce94928aec159956d1a61fc93bb949dDavid 'Digit' Turner     * We only support this when hw.keyboard.lid is true.
514b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project     */
5158b9887163ce94928aec159956d1a61fc93bb949dDavid 'Digit' Turner    if (config->hw_keyboard && config->hw_keyboard_lid) {
516b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit(s, EV_SYN, EV_SW);
517b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project        events_set_bit(s, EV_SW, 0);
518b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project    }
519b059facee5eb498c78c573617c62cc13eddc8644The Android Open Source Project
5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iomemtype = cpu_register_io_memory(events_readfn, events_writefn, s);
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_register_physical_memory(base, 0xfff, iomemtype);
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_add_kbd_event_handler(events_put_keycode, s);
5255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_add_mouse_event_handler(events_put_mouse, s, 1, "goldfish-events");
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->base = base;
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->irq = irq;
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->first = 0;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->last = 0;
53280bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    s->state = STATE_INIT;
533aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    s->name = g_strdup(config->hw_keyboard_charmap);
53480bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner
53580bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    /* This function migh fire buffered events to the device, so
53680bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner     * ensure that it is called after initialization is complete
53780bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner     */
53880bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    user_event_register_generic(s, events_put_generic);
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5405cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner    register_savevm(NULL,
5415cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    "events_state",
5425cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    0,
5435cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    EVENTS_STATE_SAVE_VERSION,
5445cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    events_state_save,
5455cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    events_state_load,
5465cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    s);
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
548