Revision b976b4c0

b/hw/pxa2xx_keypad.c
82 82
struct PXA2xxKeyPadState {
83 83
    qemu_irq    irq;
84 84
    struct  keymap *map;
85
    int         pressed_cnt;
85 86

  
86 87
    uint32_t    kpc;
87 88
    uint32_t    kpdk;
88 89
    uint32_t    kprec;
89 90
    uint32_t    kpmk;
90 91
    uint32_t    kpas;
91
    uint32_t    kpasmkp0;
92
    uint32_t    kpasmkp1;
93
    uint32_t    kpasmkp2;
94
    uint32_t    kpasmkp3;
92
    uint32_t    kpasmkp[4];
95 93
    uint32_t    kpkdi;
96 94
};
97 95

  
96
static void pxa27x_keypad_find_pressed_key(PXA2xxKeyPadState *kp, int *row, int *col)
97
{
98
    int i;
99
    for (i = 0; i < 4; i++)
100
    {
101
        *col = i * 2;
102
        for (*row = 0; *row < 8; (*row)++) {
103
            if (kp->kpasmkp[i] & (1 << *row))
104
                return;
105
        }
106
        *col = i * 2 + 1;
107
        for (*row = 0; *row < 8; (*row)++) {
108
            if (kp->kpasmkp[i] & (1 << (*row + 16)))
109
                return;
110
        }
111
    }
112
}
113

  
98 114
static void pxa27x_keyboard_event (PXA2xxKeyPadState *kp, int keycode)
99 115
{
100
    int row, col,rel;
116
    int row, col, rel, assert_irq = 0;
117
    uint32_t val;
101 118

  
102 119
    if(!(kp->kpc & KPC_ME)) /* skip if not enabled */
103 120
        return;
......
108 125

  
109 126
        rel = (keycode & 0x80) ? 1 : 0; /* key release from qemu */
110 127
        keycode &= ~(0x80); /* strip qemu key release bit */
128

  
111 129
        row = kp->map[keycode].row;
112 130
        col = kp->map[keycode].column;
113 131
        if(row == -1 || col == -1)
114 132
            return;
115
        switch (col) {
116
        case 0:
117
        case 1:
118
            if(rel)
119
                kp->kpasmkp0 = ~(0xffffffff);
120
            else
121
                kp->kpasmkp0 |= KPASMKPx_MKC(row,col);
122
            break;
123
        case 2:
124
        case 3:
125
            if(rel)
126
                kp->kpasmkp1 = ~(0xffffffff);
127
            else
128
                kp->kpasmkp1 |= KPASMKPx_MKC(row,col);
129
            break;
130
        case 4:
131
        case 5:
132
            if(rel)
133
                kp->kpasmkp2 = ~(0xffffffff);
134
            else
135
                kp->kpasmkp2 |= KPASMKPx_MKC(row,col);
136
            break;
137
        case 6:
138
        case 7:
139
            if(rel)
140
                kp->kpasmkp3 = ~(0xffffffff);
141
            else
142
                kp->kpasmkp3 |= KPASMKPx_MKC(row,col);
143
            break;
144
        } /* switch */
133

  
134
        val = KPASMKPx_MKC(row, col);
135
        if (rel) {
136
            if (kp->kpasmkp[col / 2] & val) {
137
                kp->kpasmkp[col / 2] &= ~val;
138
                kp->pressed_cnt--;
139
                assert_irq = 1;
140
            }
141
        } else {
142
            if (!(kp->kpasmkp[col / 2] & val)) {
143
                kp->kpasmkp[col / 2] |= val;
144
                kp->pressed_cnt++;
145
                assert_irq = 1;
146
            }
147
        }
148
        kp->kpas = ((kp->pressed_cnt & 0x1f) << 26) | (0xf << 4) | 0xf;
149
        if (kp->pressed_cnt == 1) {
150
            kp->kpas &= ~((0xf << 4) | 0xf);
151
            if (rel)
152
                pxa27x_keypad_find_pressed_key(kp, &row, &col);
153
            kp->kpas |= ((row & 0xf) << 4) | (col & 0xf);
154
        }
145 155
        goto out;
146 156
    }
147 157
    return;
148 158

  
149 159
out:
150
    if(kp->kpc & KPC_MIE) {
160
    if (assert_irq && (kp->kpc & KPC_MIE)) {
151 161
        kp->kpc |= KPC_MI;
152 162
        qemu_irq_raise(kp->irq);
153 163
    }
......
194 204
        return s->kpas;
195 205
        break;
196 206
    case KPASMKP0:
197
        return s->kpasmkp0;
207
        return s->kpasmkp[0];
198 208
        break;
199 209
    case KPASMKP1:
200
        return s->kpasmkp1;
210
        return s->kpasmkp[1];
201 211
        break;
202 212
    case KPASMKP2:
203
        return s->kpasmkp2;
213
        return s->kpasmkp[2];
204 214
        break;
205 215
    case KPASMKP3:
206
        return s->kpasmkp3;
216
        return s->kpasmkp[3];
207 217
        break;
208 218
    case KPKDI:
209 219
        return s->kpkdi;
......
237 247
        s->kpas = value;
238 248
        break;
239 249
    case KPASMKP0:
240
        s->kpasmkp0 = value;
250
        s->kpasmkp[0] = value;
241 251
        break;
242 252
    case KPASMKP1:
243
        s->kpasmkp1 = value;
253
        s->kpasmkp[1] = value;
244 254
        break;
245 255
    case KPASMKP2:
246
        s->kpasmkp2 = value;
256
        s->kpasmkp[2] = value;
247 257
        break;
248 258
    case KPASMKP3:
249
        s->kpasmkp3 = value;
259
        s->kpasmkp[3] = value;
250 260
        break;
251 261
    case KPKDI:
252 262
        s->kpkdi = value;
......
278 288
    qemu_put_be32s(f, &s->kprec);
279 289
    qemu_put_be32s(f, &s->kpmk);
280 290
    qemu_put_be32s(f, &s->kpas);
281
    qemu_put_be32s(f, &s->kpasmkp0);
282
    qemu_put_be32s(f, &s->kpasmkp1);
283
    qemu_put_be32s(f, &s->kpasmkp2);
284
    qemu_put_be32s(f, &s->kpasmkp3);
291
    qemu_put_be32s(f, &s->kpasmkp[0]);
292
    qemu_put_be32s(f, &s->kpasmkp[1]);
293
    qemu_put_be32s(f, &s->kpasmkp[2]);
294
    qemu_put_be32s(f, &s->kpasmkp[3]);
285 295
    qemu_put_be32s(f, &s->kpkdi);
286 296

  
287 297
}
......
295 305
    qemu_get_be32s(f, &s->kprec);
296 306
    qemu_get_be32s(f, &s->kpmk);
297 307
    qemu_get_be32s(f, &s->kpas);
298
    qemu_get_be32s(f, &s->kpasmkp0);
299
    qemu_get_be32s(f, &s->kpasmkp1);
300
    qemu_get_be32s(f, &s->kpasmkp2);
301
    qemu_get_be32s(f, &s->kpasmkp3);
308
    qemu_get_be32s(f, &s->kpasmkp[0]);
309
    qemu_get_be32s(f, &s->kpasmkp[1]);
310
    qemu_get_be32s(f, &s->kpasmkp[2]);
311
    qemu_get_be32s(f, &s->kpasmkp[3]);
302 312
    qemu_get_be32s(f, &s->kpkdi);
303 313

  
304 314
    return 0;

Also available in: Unified diff