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