root / hw / input / ps2.c @ a8aec295
History | View | Annotate | Download (20.4 kB)
1 | 0e43e99c | bellard | /*
|
---|---|---|---|
2 | 0e43e99c | bellard | * QEMU PS/2 keyboard/mouse emulation
|
3 | 5fafdf24 | ths | *
|
4 | 0e43e99c | bellard | * Copyright (c) 2003 Fabrice Bellard
|
5 | 5fafdf24 | ths | *
|
6 | 0e43e99c | bellard | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 0e43e99c | bellard | * of this software and associated documentation files (the "Software"), to deal
|
8 | 0e43e99c | bellard | * in the Software without restriction, including without limitation the rights
|
9 | 0e43e99c | bellard | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 0e43e99c | bellard | * copies of the Software, and to permit persons to whom the Software is
|
11 | 0e43e99c | bellard | * furnished to do so, subject to the following conditions:
|
12 | 0e43e99c | bellard | *
|
13 | 0e43e99c | bellard | * The above copyright notice and this permission notice shall be included in
|
14 | 0e43e99c | bellard | * all copies or substantial portions of the Software.
|
15 | 0e43e99c | bellard | *
|
16 | 0e43e99c | bellard | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 0e43e99c | bellard | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 0e43e99c | bellard | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 0e43e99c | bellard | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 0e43e99c | bellard | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 0e43e99c | bellard | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 0e43e99c | bellard | * THE SOFTWARE.
|
23 | 0e43e99c | bellard | */
|
24 | 83c9f4ca | Paolo Bonzini | #include "hw/hw.h" |
25 | 0d09e41a | Paolo Bonzini | #include "hw/input/ps2.h" |
26 | 28ecbaee | Paolo Bonzini | #include "ui/console.h" |
27 | 9c17d615 | Paolo Bonzini | #include "sysemu/sysemu.h" |
28 | 0e43e99c | bellard | |
29 | 0e43e99c | bellard | /* debug PC keyboard */
|
30 | 0e43e99c | bellard | //#define DEBUG_KBD
|
31 | 0e43e99c | bellard | |
32 | 0e43e99c | bellard | /* debug PC keyboard : only mouse */
|
33 | 0e43e99c | bellard | //#define DEBUG_MOUSE
|
34 | 0e43e99c | bellard | |
35 | 0e43e99c | bellard | /* Keyboard Commands */
|
36 | 0e43e99c | bellard | #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ |
37 | 0e43e99c | bellard | #define KBD_CMD_ECHO 0xEE |
38 | e7d93956 | aurel32 | #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */ |
39 | 0e43e99c | bellard | #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */ |
40 | 0e43e99c | bellard | #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ |
41 | 0e43e99c | bellard | #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ |
42 | 0e43e99c | bellard | #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */ |
43 | 0e43e99c | bellard | #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */ |
44 | 0e43e99c | bellard | #define KBD_CMD_RESET 0xFF /* Reset */ |
45 | 0e43e99c | bellard | |
46 | 0e43e99c | bellard | /* Keyboard Replies */
|
47 | 0e43e99c | bellard | #define KBD_REPLY_POR 0xAA /* Power on reset */ |
48 | 35c4d671 | aurel32 | #define KBD_REPLY_ID 0xAB /* Keyboard ID */ |
49 | 0e43e99c | bellard | #define KBD_REPLY_ACK 0xFA /* Command ACK */ |
50 | 0e43e99c | bellard | #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ |
51 | 0e43e99c | bellard | |
52 | 0e43e99c | bellard | /* Mouse Commands */
|
53 | 0e43e99c | bellard | #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ |
54 | 0e43e99c | bellard | #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ |
55 | 0e43e99c | bellard | #define AUX_SET_RES 0xE8 /* Set resolution */ |
56 | 0e43e99c | bellard | #define AUX_GET_SCALE 0xE9 /* Get scaling factor */ |
57 | 0e43e99c | bellard | #define AUX_SET_STREAM 0xEA /* Set stream mode */ |
58 | 0e43e99c | bellard | #define AUX_POLL 0xEB /* Poll */ |
59 | 0e43e99c | bellard | #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */ |
60 | 0e43e99c | bellard | #define AUX_SET_WRAP 0xEE /* Set wrap mode */ |
61 | 0e43e99c | bellard | #define AUX_SET_REMOTE 0xF0 /* Set remote mode */ |
62 | 0e43e99c | bellard | #define AUX_GET_TYPE 0xF2 /* Get type */ |
63 | 0e43e99c | bellard | #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ |
64 | 0e43e99c | bellard | #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ |
65 | 0e43e99c | bellard | #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ |
66 | 0e43e99c | bellard | #define AUX_SET_DEFAULT 0xF6 |
67 | 0e43e99c | bellard | #define AUX_RESET 0xFF /* Reset aux device */ |
68 | 0e43e99c | bellard | #define AUX_ACK 0xFA /* Command byte ACK. */ |
69 | 0e43e99c | bellard | |
70 | 0e43e99c | bellard | #define MOUSE_STATUS_REMOTE 0x40 |
71 | 0e43e99c | bellard | #define MOUSE_STATUS_ENABLED 0x20 |
72 | 0e43e99c | bellard | #define MOUSE_STATUS_SCALE21 0x10 |
73 | 0e43e99c | bellard | |
74 | 0e43e99c | bellard | #define PS2_QUEUE_SIZE 256 |
75 | 0e43e99c | bellard | |
76 | 0e43e99c | bellard | typedef struct { |
77 | 0e43e99c | bellard | uint8_t data[PS2_QUEUE_SIZE]; |
78 | 0e43e99c | bellard | int rptr, wptr, count;
|
79 | 0e43e99c | bellard | } PS2Queue; |
80 | 0e43e99c | bellard | |
81 | 0e43e99c | bellard | typedef struct { |
82 | 0e43e99c | bellard | PS2Queue queue; |
83 | 0e43e99c | bellard | int32_t write_cmd; |
84 | 0e43e99c | bellard | void (*update_irq)(void *, int); |
85 | 0e43e99c | bellard | void *update_arg;
|
86 | 0e43e99c | bellard | } PS2State; |
87 | 0e43e99c | bellard | |
88 | 0e43e99c | bellard | typedef struct { |
89 | 0e43e99c | bellard | PS2State common; |
90 | 0e43e99c | bellard | int scan_enabled;
|
91 | 5cbdb3a3 | Stefan Weil | /* QEMU uses translated PC scancodes internally. To avoid multiple
|
92 | f94f5d71 | pbrook | conversions we do the translation (if any) in the PS/2 emulation
|
93 | f94f5d71 | pbrook | not the keyboard controller. */
|
94 | f94f5d71 | pbrook | int translate;
|
95 | e7d93956 | aurel32 | int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */ |
96 | 7f540ab5 | Christophe Fergeau | int ledstate;
|
97 | 0e43e99c | bellard | } PS2KbdState; |
98 | 0e43e99c | bellard | |
99 | 0e43e99c | bellard | typedef struct { |
100 | 0e43e99c | bellard | PS2State common; |
101 | 0e43e99c | bellard | uint8_t mouse_status; |
102 | 0e43e99c | bellard | uint8_t mouse_resolution; |
103 | 0e43e99c | bellard | uint8_t mouse_sample_rate; |
104 | 0e43e99c | bellard | uint8_t mouse_wrap; |
105 | 0e43e99c | bellard | uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
|
106 | 0e43e99c | bellard | uint8_t mouse_detect_state; |
107 | 0e43e99c | bellard | int mouse_dx; /* current values, needed for 'poll' mode */ |
108 | 0e43e99c | bellard | int mouse_dy;
|
109 | 0e43e99c | bellard | int mouse_dz;
|
110 | 0e43e99c | bellard | uint8_t mouse_buttons; |
111 | 0e43e99c | bellard | } PS2MouseState; |
112 | 0e43e99c | bellard | |
113 | f94f5d71 | pbrook | /* Table to convert from PC scancodes to raw scancodes. */
|
114 | f94f5d71 | pbrook | static const unsigned char ps2_raw_keycode[128] = { |
115 | 7096a96d | Roy Tam | 0, 118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13, |
116 | 7096a96d | Roy Tam | 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27, |
117 | 7096a96d | Roy Tam | 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42, |
118 | 7096a96d | Roy Tam | 50, 49, 58, 65, 73, 74, 89, 124, 17, 41, 88, 5, 6, 4, 12, 3, |
119 | 7096a96d | Roy Tam | 11, 2, 10, 1, 9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105, |
120 | 7096a96d | Roy Tam | 114, 122, 112, 113, 127, 96, 97, 120, 7, 15, 23, 31, 39, 47, 55, 63, |
121 | 7096a96d | Roy Tam | 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111, |
122 | 7096a96d | Roy Tam | 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110 |
123 | 7096a96d | Roy Tam | }; |
124 | 7096a96d | Roy Tam | static const unsigned char ps2_raw_keycode_set3[128] = { |
125 | 7096a96d | Roy Tam | 0, 8, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13, |
126 | 7096a96d | Roy Tam | 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 17, 28, 27, |
127 | 7096a96d | Roy Tam | 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 92, 26, 34, 33, 42, |
128 | 7096a96d | Roy Tam | 50, 49, 58, 65, 73, 74, 89, 126, 25, 41, 20, 7, 15, 23, 31, 39, |
129 | 7096a96d | Roy Tam | 47, 2, 63, 71, 79, 118, 95, 108, 117, 125, 132, 107, 115, 116, 124, 105, |
130 | 7096a96d | Roy Tam | 114, 122, 112, 113, 127, 96, 97, 86, 94, 15, 23, 31, 39, 47, 55, 63, |
131 | 7096a96d | Roy Tam | 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111, |
132 | 7096a96d | Roy Tam | 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110 |
133 | f94f5d71 | pbrook | }; |
134 | f94f5d71 | pbrook | |
135 | 0e43e99c | bellard | void ps2_queue(void *opaque, int b) |
136 | 0e43e99c | bellard | { |
137 | 0e43e99c | bellard | PS2State *s = (PS2State *)opaque; |
138 | 0e43e99c | bellard | PS2Queue *q = &s->queue; |
139 | 0e43e99c | bellard | |
140 | 0e43e99c | bellard | if (q->count >= PS2_QUEUE_SIZE)
|
141 | 0e43e99c | bellard | return;
|
142 | 0e43e99c | bellard | q->data[q->wptr] = b; |
143 | 0e43e99c | bellard | if (++q->wptr == PS2_QUEUE_SIZE)
|
144 | 0e43e99c | bellard | q->wptr = 0;
|
145 | 0e43e99c | bellard | q->count++; |
146 | 0e43e99c | bellard | s->update_irq(s->update_arg, 1);
|
147 | 0e43e99c | bellard | } |
148 | 0e43e99c | bellard | |
149 | 35c4d671 | aurel32 | /*
|
150 | 35c4d671 | aurel32 | keycode is expressed as follow:
|
151 | 35c4d671 | aurel32 | bit 7 - 0 key pressed, 1 = key released
|
152 | 35c4d671 | aurel32 | bits 6-0 - translated scancode set 2
|
153 | 35c4d671 | aurel32 | */
|
154 | 0e43e99c | bellard | static void ps2_put_keycode(void *opaque, int keycode) |
155 | 0e43e99c | bellard | { |
156 | f94f5d71 | pbrook | PS2KbdState *s = opaque; |
157 | e7d93956 | aurel32 | |
158 | fd214d18 | Gerd Hoffmann | qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); |
159 | 7096a96d | Roy Tam | /* XXX: add support for scancode set 1 */
|
160 | 7096a96d | Roy Tam | if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) { |
161 | 7096a96d | Roy Tam | if (keycode & 0x80) { |
162 | f94f5d71 | pbrook | ps2_queue(&s->common, 0xf0);
|
163 | 7096a96d | Roy Tam | } |
164 | 7096a96d | Roy Tam | if (s->scancode_set == 2) { |
165 | 7096a96d | Roy Tam | keycode = ps2_raw_keycode[keycode & 0x7f];
|
166 | 7096a96d | Roy Tam | } else if (s->scancode_set == 3) { |
167 | 7096a96d | Roy Tam | keycode = ps2_raw_keycode_set3[keycode & 0x7f];
|
168 | 7096a96d | Roy Tam | } |
169 | f94f5d71 | pbrook | } |
170 | 0e43e99c | bellard | ps2_queue(&s->common, keycode); |
171 | 0e43e99c | bellard | } |
172 | 0e43e99c | bellard | |
173 | 0e43e99c | bellard | uint32_t ps2_read_data(void *opaque)
|
174 | 0e43e99c | bellard | { |
175 | 0e43e99c | bellard | PS2State *s = (PS2State *)opaque; |
176 | 0e43e99c | bellard | PS2Queue *q; |
177 | 0e43e99c | bellard | int val, index;
|
178 | 3b46e624 | ths | |
179 | 0e43e99c | bellard | q = &s->queue; |
180 | 0e43e99c | bellard | if (q->count == 0) { |
181 | 0e43e99c | bellard | /* NOTE: if no data left, we return the last keyboard one
|
182 | 0e43e99c | bellard | (needed for EMM386) */
|
183 | 0e43e99c | bellard | /* XXX: need a timer to do things correctly */
|
184 | 0e43e99c | bellard | index = q->rptr - 1;
|
185 | 0e43e99c | bellard | if (index < 0) |
186 | 0e43e99c | bellard | index = PS2_QUEUE_SIZE - 1;
|
187 | 0e43e99c | bellard | val = q->data[index]; |
188 | 0e43e99c | bellard | } else {
|
189 | 0e43e99c | bellard | val = q->data[q->rptr]; |
190 | 0e43e99c | bellard | if (++q->rptr == PS2_QUEUE_SIZE)
|
191 | 0e43e99c | bellard | q->rptr = 0;
|
192 | 0e43e99c | bellard | q->count--; |
193 | 0e43e99c | bellard | /* reading deasserts IRQ */
|
194 | 0e43e99c | bellard | s->update_irq(s->update_arg, 0);
|
195 | 0e43e99c | bellard | /* reassert IRQs if data left */
|
196 | 0e43e99c | bellard | s->update_irq(s->update_arg, q->count != 0);
|
197 | 0e43e99c | bellard | } |
198 | 0e43e99c | bellard | return val;
|
199 | 0e43e99c | bellard | } |
200 | 0e43e99c | bellard | |
201 | 7f540ab5 | Christophe Fergeau | static void ps2_set_ledstate(PS2KbdState *s, int ledstate) |
202 | 7f540ab5 | Christophe Fergeau | { |
203 | 7f540ab5 | Christophe Fergeau | s->ledstate = ledstate; |
204 | 7f540ab5 | Christophe Fergeau | kbd_put_ledstate(ledstate); |
205 | 7f540ab5 | Christophe Fergeau | } |
206 | 7f540ab5 | Christophe Fergeau | |
207 | 0e43e99c | bellard | static void ps2_reset_keyboard(PS2KbdState *s) |
208 | 0e43e99c | bellard | { |
209 | 0e43e99c | bellard | s->scan_enabled = 1;
|
210 | e7d93956 | aurel32 | s->scancode_set = 2;
|
211 | 7f540ab5 | Christophe Fergeau | ps2_set_ledstate(s, 0);
|
212 | 0e43e99c | bellard | } |
213 | 0e43e99c | bellard | |
214 | 0e43e99c | bellard | void ps2_write_keyboard(void *opaque, int val) |
215 | 0e43e99c | bellard | { |
216 | 0e43e99c | bellard | PS2KbdState *s = (PS2KbdState *)opaque; |
217 | 0e43e99c | bellard | |
218 | 0e43e99c | bellard | switch(s->common.write_cmd) {
|
219 | 0e43e99c | bellard | default:
|
220 | 0e43e99c | bellard | case -1: |
221 | 0e43e99c | bellard | switch(val) {
|
222 | 0e43e99c | bellard | case 0x00: |
223 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_ACK); |
224 | 0e43e99c | bellard | break;
|
225 | 0e43e99c | bellard | case 0x05: |
226 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_RESEND); |
227 | 0e43e99c | bellard | break;
|
228 | 0e43e99c | bellard | case KBD_CMD_GET_ID:
|
229 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_ACK); |
230 | e7d93956 | aurel32 | /* We emulate a MF2 AT keyboard here */
|
231 | 35c4d671 | aurel32 | ps2_queue(&s->common, KBD_REPLY_ID); |
232 | 35c4d671 | aurel32 | if (s->translate)
|
233 | 35c4d671 | aurel32 | ps2_queue(&s->common, 0x41);
|
234 | 35c4d671 | aurel32 | else
|
235 | 35c4d671 | aurel32 | ps2_queue(&s->common, 0x83);
|
236 | 0e43e99c | bellard | break;
|
237 | 0e43e99c | bellard | case KBD_CMD_ECHO:
|
238 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_CMD_ECHO); |
239 | 0e43e99c | bellard | break;
|
240 | 0e43e99c | bellard | case KBD_CMD_ENABLE:
|
241 | 0e43e99c | bellard | s->scan_enabled = 1;
|
242 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_ACK); |
243 | 0e43e99c | bellard | break;
|
244 | e7d93956 | aurel32 | case KBD_CMD_SCANCODE:
|
245 | 0e43e99c | bellard | case KBD_CMD_SET_LEDS:
|
246 | 0e43e99c | bellard | case KBD_CMD_SET_RATE:
|
247 | 0e43e99c | bellard | s->common.write_cmd = val; |
248 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_ACK); |
249 | 0e43e99c | bellard | break;
|
250 | 0e43e99c | bellard | case KBD_CMD_RESET_DISABLE:
|
251 | 0e43e99c | bellard | ps2_reset_keyboard(s); |
252 | 0e43e99c | bellard | s->scan_enabled = 0;
|
253 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_ACK); |
254 | 0e43e99c | bellard | break;
|
255 | 0e43e99c | bellard | case KBD_CMD_RESET_ENABLE:
|
256 | 0e43e99c | bellard | ps2_reset_keyboard(s); |
257 | 0e43e99c | bellard | s->scan_enabled = 1;
|
258 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_ACK); |
259 | 0e43e99c | bellard | break;
|
260 | 0e43e99c | bellard | case KBD_CMD_RESET:
|
261 | 0e43e99c | bellard | ps2_reset_keyboard(s); |
262 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_ACK); |
263 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_POR); |
264 | 0e43e99c | bellard | break;
|
265 | 0e43e99c | bellard | default:
|
266 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_ACK); |
267 | 0e43e99c | bellard | break;
|
268 | 0e43e99c | bellard | } |
269 | 0e43e99c | bellard | break;
|
270 | e7d93956 | aurel32 | case KBD_CMD_SCANCODE:
|
271 | e7d93956 | aurel32 | if (val == 0) { |
272 | e7d93956 | aurel32 | if (s->scancode_set == 1) |
273 | e7d93956 | aurel32 | ps2_put_keycode(s, 0x43);
|
274 | e7d93956 | aurel32 | else if (s->scancode_set == 2) |
275 | e7d93956 | aurel32 | ps2_put_keycode(s, 0x41);
|
276 | e7d93956 | aurel32 | else if (s->scancode_set == 3) |
277 | e7d93956 | aurel32 | ps2_put_keycode(s, 0x3f);
|
278 | e7d93956 | aurel32 | } else {
|
279 | e7d93956 | aurel32 | if (val >= 1 && val <= 3) |
280 | e7d93956 | aurel32 | s->scancode_set = val; |
281 | e7d93956 | aurel32 | ps2_queue(&s->common, KBD_REPLY_ACK); |
282 | e7d93956 | aurel32 | } |
283 | e7d93956 | aurel32 | s->common.write_cmd = -1;
|
284 | e7d93956 | aurel32 | break;
|
285 | 0e43e99c | bellard | case KBD_CMD_SET_LEDS:
|
286 | 7f540ab5 | Christophe Fergeau | ps2_set_ledstate(s, val); |
287 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_ACK); |
288 | 0e43e99c | bellard | s->common.write_cmd = -1;
|
289 | 0e43e99c | bellard | break;
|
290 | 0e43e99c | bellard | case KBD_CMD_SET_RATE:
|
291 | 0e43e99c | bellard | ps2_queue(&s->common, KBD_REPLY_ACK); |
292 | 0e43e99c | bellard | s->common.write_cmd = -1;
|
293 | 0e43e99c | bellard | break;
|
294 | 0e43e99c | bellard | } |
295 | 0e43e99c | bellard | } |
296 | 0e43e99c | bellard | |
297 | f94f5d71 | pbrook | /* Set the scancode translation mode.
|
298 | f94f5d71 | pbrook | 0 = raw scancodes.
|
299 | f94f5d71 | pbrook | 1 = translated scancodes (used by qemu internally). */
|
300 | f94f5d71 | pbrook | |
301 | f94f5d71 | pbrook | void ps2_keyboard_set_translation(void *opaque, int mode) |
302 | f94f5d71 | pbrook | { |
303 | f94f5d71 | pbrook | PS2KbdState *s = (PS2KbdState *)opaque; |
304 | f94f5d71 | pbrook | s->translate = mode; |
305 | f94f5d71 | pbrook | } |
306 | f94f5d71 | pbrook | |
307 | 0e43e99c | bellard | static void ps2_mouse_send_packet(PS2MouseState *s) |
308 | 0e43e99c | bellard | { |
309 | 0e43e99c | bellard | unsigned int b; |
310 | 0e43e99c | bellard | int dx1, dy1, dz1;
|
311 | 0e43e99c | bellard | |
312 | 0e43e99c | bellard | dx1 = s->mouse_dx; |
313 | 0e43e99c | bellard | dy1 = s->mouse_dy; |
314 | 0e43e99c | bellard | dz1 = s->mouse_dz; |
315 | 0e43e99c | bellard | /* XXX: increase range to 8 bits ? */
|
316 | 0e43e99c | bellard | if (dx1 > 127) |
317 | 0e43e99c | bellard | dx1 = 127;
|
318 | 0e43e99c | bellard | else if (dx1 < -127) |
319 | 0e43e99c | bellard | dx1 = -127;
|
320 | 0e43e99c | bellard | if (dy1 > 127) |
321 | 0e43e99c | bellard | dy1 = 127;
|
322 | 0e43e99c | bellard | else if (dy1 < -127) |
323 | 0e43e99c | bellard | dy1 = -127;
|
324 | 0e43e99c | bellard | b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); |
325 | 0e43e99c | bellard | ps2_queue(&s->common, b); |
326 | 0e43e99c | bellard | ps2_queue(&s->common, dx1 & 0xff);
|
327 | 0e43e99c | bellard | ps2_queue(&s->common, dy1 & 0xff);
|
328 | 0e43e99c | bellard | /* extra byte for IMPS/2 or IMEX */
|
329 | 0e43e99c | bellard | switch(s->mouse_type) {
|
330 | 0e43e99c | bellard | default:
|
331 | 0e43e99c | bellard | break;
|
332 | 0e43e99c | bellard | case 3: |
333 | 0e43e99c | bellard | if (dz1 > 127) |
334 | 0e43e99c | bellard | dz1 = 127;
|
335 | 0e43e99c | bellard | else if (dz1 < -127) |
336 | 0e43e99c | bellard | dz1 = -127;
|
337 | 0e43e99c | bellard | ps2_queue(&s->common, dz1 & 0xff);
|
338 | 0e43e99c | bellard | break;
|
339 | 0e43e99c | bellard | case 4: |
340 | 0e43e99c | bellard | if (dz1 > 7) |
341 | 0e43e99c | bellard | dz1 = 7;
|
342 | 0e43e99c | bellard | else if (dz1 < -7) |
343 | 0e43e99c | bellard | dz1 = -7;
|
344 | 0e43e99c | bellard | b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); |
345 | 0e43e99c | bellard | ps2_queue(&s->common, b); |
346 | 0e43e99c | bellard | break;
|
347 | 0e43e99c | bellard | } |
348 | 0e43e99c | bellard | |
349 | 0e43e99c | bellard | /* update deltas */
|
350 | 0e43e99c | bellard | s->mouse_dx -= dx1; |
351 | 0e43e99c | bellard | s->mouse_dy -= dy1; |
352 | 0e43e99c | bellard | s->mouse_dz -= dz1; |
353 | 0e43e99c | bellard | } |
354 | 0e43e99c | bellard | |
355 | 5fafdf24 | ths | static void ps2_mouse_event(void *opaque, |
356 | 0e43e99c | bellard | int dx, int dy, int dz, int buttons_state) |
357 | 0e43e99c | bellard | { |
358 | 0e43e99c | bellard | PS2MouseState *s = opaque; |
359 | 0e43e99c | bellard | |
360 | 0e43e99c | bellard | /* check if deltas are recorded when disabled */
|
361 | 0e43e99c | bellard | if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
|
362 | 0e43e99c | bellard | return;
|
363 | 0e43e99c | bellard | |
364 | 0e43e99c | bellard | s->mouse_dx += dx; |
365 | 0e43e99c | bellard | s->mouse_dy -= dy; |
366 | 0e43e99c | bellard | s->mouse_dz += dz; |
367 | 0e43e99c | bellard | /* XXX: SDL sometimes generates nul events: we delete them */
|
368 | 0e43e99c | bellard | if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 && |
369 | 0e43e99c | bellard | s->mouse_buttons == buttons_state) |
370 | 0e43e99c | bellard | return;
|
371 | 0e43e99c | bellard | s->mouse_buttons = buttons_state; |
372 | 3b46e624 | ths | |
373 | fd214d18 | Gerd Hoffmann | if (buttons_state) {
|
374 | fd214d18 | Gerd Hoffmann | qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); |
375 | fd214d18 | Gerd Hoffmann | } |
376 | fd214d18 | Gerd Hoffmann | |
377 | 0e43e99c | bellard | if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
|
378 | 0e43e99c | bellard | (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
|
379 | 0e43e99c | bellard | for(;;) {
|
380 | 0e43e99c | bellard | /* if not remote, send event. Multiple events are sent if
|
381 | 0e43e99c | bellard | too big deltas */
|
382 | 0e43e99c | bellard | ps2_mouse_send_packet(s); |
383 | 0e43e99c | bellard | if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) |
384 | 0e43e99c | bellard | break;
|
385 | 0e43e99c | bellard | } |
386 | 0e43e99c | bellard | } |
387 | 0e43e99c | bellard | } |
388 | 0e43e99c | bellard | |
389 | 548df2ac | ths | void ps2_mouse_fake_event(void *opaque) |
390 | 548df2ac | ths | { |
391 | 548df2ac | ths | ps2_mouse_event(opaque, 1, 0, 0, 0); |
392 | 548df2ac | ths | } |
393 | 548df2ac | ths | |
394 | 0e43e99c | bellard | void ps2_write_mouse(void *opaque, int val) |
395 | 0e43e99c | bellard | { |
396 | 0e43e99c | bellard | PS2MouseState *s = (PS2MouseState *)opaque; |
397 | 0e43e99c | bellard | #ifdef DEBUG_MOUSE
|
398 | 0e43e99c | bellard | printf("kbd: write mouse 0x%02x\n", val);
|
399 | 0e43e99c | bellard | #endif
|
400 | 0e43e99c | bellard | switch(s->common.write_cmd) {
|
401 | 0e43e99c | bellard | default:
|
402 | 0e43e99c | bellard | case -1: |
403 | 0e43e99c | bellard | /* mouse command */
|
404 | 0e43e99c | bellard | if (s->mouse_wrap) {
|
405 | 0e43e99c | bellard | if (val == AUX_RESET_WRAP) {
|
406 | 0e43e99c | bellard | s->mouse_wrap = 0;
|
407 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
408 | 0e43e99c | bellard | return;
|
409 | 0e43e99c | bellard | } else if (val != AUX_RESET) { |
410 | 0e43e99c | bellard | ps2_queue(&s->common, val); |
411 | 0e43e99c | bellard | return;
|
412 | 0e43e99c | bellard | } |
413 | 0e43e99c | bellard | } |
414 | 0e43e99c | bellard | switch(val) {
|
415 | 0e43e99c | bellard | case AUX_SET_SCALE11:
|
416 | 0e43e99c | bellard | s->mouse_status &= ~MOUSE_STATUS_SCALE21; |
417 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
418 | 0e43e99c | bellard | break;
|
419 | 0e43e99c | bellard | case AUX_SET_SCALE21:
|
420 | 0e43e99c | bellard | s->mouse_status |= MOUSE_STATUS_SCALE21; |
421 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
422 | 0e43e99c | bellard | break;
|
423 | 0e43e99c | bellard | case AUX_SET_STREAM:
|
424 | 0e43e99c | bellard | s->mouse_status &= ~MOUSE_STATUS_REMOTE; |
425 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
426 | 0e43e99c | bellard | break;
|
427 | 0e43e99c | bellard | case AUX_SET_WRAP:
|
428 | 0e43e99c | bellard | s->mouse_wrap = 1;
|
429 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
430 | 0e43e99c | bellard | break;
|
431 | 0e43e99c | bellard | case AUX_SET_REMOTE:
|
432 | 0e43e99c | bellard | s->mouse_status |= MOUSE_STATUS_REMOTE; |
433 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
434 | 0e43e99c | bellard | break;
|
435 | 0e43e99c | bellard | case AUX_GET_TYPE:
|
436 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
437 | 0e43e99c | bellard | ps2_queue(&s->common, s->mouse_type); |
438 | 0e43e99c | bellard | break;
|
439 | 0e43e99c | bellard | case AUX_SET_RES:
|
440 | 0e43e99c | bellard | case AUX_SET_SAMPLE:
|
441 | 0e43e99c | bellard | s->common.write_cmd = val; |
442 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
443 | 0e43e99c | bellard | break;
|
444 | 0e43e99c | bellard | case AUX_GET_SCALE:
|
445 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
446 | 0e43e99c | bellard | ps2_queue(&s->common, s->mouse_status); |
447 | 0e43e99c | bellard | ps2_queue(&s->common, s->mouse_resolution); |
448 | 0e43e99c | bellard | ps2_queue(&s->common, s->mouse_sample_rate); |
449 | 0e43e99c | bellard | break;
|
450 | 0e43e99c | bellard | case AUX_POLL:
|
451 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
452 | 0e43e99c | bellard | ps2_mouse_send_packet(s); |
453 | 0e43e99c | bellard | break;
|
454 | 0e43e99c | bellard | case AUX_ENABLE_DEV:
|
455 | 0e43e99c | bellard | s->mouse_status |= MOUSE_STATUS_ENABLED; |
456 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
457 | 0e43e99c | bellard | break;
|
458 | 0e43e99c | bellard | case AUX_DISABLE_DEV:
|
459 | 0e43e99c | bellard | s->mouse_status &= ~MOUSE_STATUS_ENABLED; |
460 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
461 | 0e43e99c | bellard | break;
|
462 | 0e43e99c | bellard | case AUX_SET_DEFAULT:
|
463 | 0e43e99c | bellard | s->mouse_sample_rate = 100;
|
464 | 0e43e99c | bellard | s->mouse_resolution = 2;
|
465 | 0e43e99c | bellard | s->mouse_status = 0;
|
466 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
467 | 0e43e99c | bellard | break;
|
468 | 0e43e99c | bellard | case AUX_RESET:
|
469 | 0e43e99c | bellard | s->mouse_sample_rate = 100;
|
470 | 0e43e99c | bellard | s->mouse_resolution = 2;
|
471 | 0e43e99c | bellard | s->mouse_status = 0;
|
472 | 0e43e99c | bellard | s->mouse_type = 0;
|
473 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
474 | 0e43e99c | bellard | ps2_queue(&s->common, 0xaa);
|
475 | 0e43e99c | bellard | ps2_queue(&s->common, s->mouse_type); |
476 | 0e43e99c | bellard | break;
|
477 | 0e43e99c | bellard | default:
|
478 | 0e43e99c | bellard | break;
|
479 | 0e43e99c | bellard | } |
480 | 0e43e99c | bellard | break;
|
481 | 0e43e99c | bellard | case AUX_SET_SAMPLE:
|
482 | 0e43e99c | bellard | s->mouse_sample_rate = val; |
483 | 0e43e99c | bellard | /* detect IMPS/2 or IMEX */
|
484 | 0e43e99c | bellard | switch(s->mouse_detect_state) {
|
485 | 0e43e99c | bellard | default:
|
486 | 0e43e99c | bellard | case 0: |
487 | 0e43e99c | bellard | if (val == 200) |
488 | 0e43e99c | bellard | s->mouse_detect_state = 1;
|
489 | 0e43e99c | bellard | break;
|
490 | 0e43e99c | bellard | case 1: |
491 | 0e43e99c | bellard | if (val == 100) |
492 | 0e43e99c | bellard | s->mouse_detect_state = 2;
|
493 | 0e43e99c | bellard | else if (val == 200) |
494 | 0e43e99c | bellard | s->mouse_detect_state = 3;
|
495 | 0e43e99c | bellard | else
|
496 | 0e43e99c | bellard | s->mouse_detect_state = 0;
|
497 | 0e43e99c | bellard | break;
|
498 | 0e43e99c | bellard | case 2: |
499 | 5fafdf24 | ths | if (val == 80) |
500 | 0e43e99c | bellard | s->mouse_type = 3; /* IMPS/2 */ |
501 | 0e43e99c | bellard | s->mouse_detect_state = 0;
|
502 | 0e43e99c | bellard | break;
|
503 | 0e43e99c | bellard | case 3: |
504 | 5fafdf24 | ths | if (val == 80) |
505 | 0e43e99c | bellard | s->mouse_type = 4; /* IMEX */ |
506 | 0e43e99c | bellard | s->mouse_detect_state = 0;
|
507 | 0e43e99c | bellard | break;
|
508 | 0e43e99c | bellard | } |
509 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
510 | 0e43e99c | bellard | s->common.write_cmd = -1;
|
511 | 0e43e99c | bellard | break;
|
512 | 0e43e99c | bellard | case AUX_SET_RES:
|
513 | 0e43e99c | bellard | s->mouse_resolution = val; |
514 | 0e43e99c | bellard | ps2_queue(&s->common, AUX_ACK); |
515 | 0e43e99c | bellard | s->common.write_cmd = -1;
|
516 | 0e43e99c | bellard | break;
|
517 | 0e43e99c | bellard | } |
518 | 0e43e99c | bellard | } |
519 | 0e43e99c | bellard | |
520 | ef74679a | Dinesh Subhraveti | static void ps2_common_reset(PS2State *s) |
521 | 0e43e99c | bellard | { |
522 | 0e43e99c | bellard | PS2Queue *q; |
523 | 0e43e99c | bellard | s->write_cmd = -1;
|
524 | 0e43e99c | bellard | q = &s->queue; |
525 | 0e43e99c | bellard | q->rptr = 0;
|
526 | 0e43e99c | bellard | q->wptr = 0;
|
527 | 0e43e99c | bellard | q->count = 0;
|
528 | deeccef3 | aliguori | s->update_irq(s->update_arg, 0);
|
529 | 0e43e99c | bellard | } |
530 | 0e43e99c | bellard | |
531 | ef74679a | Dinesh Subhraveti | static void ps2_kbd_reset(void *opaque) |
532 | ef74679a | Dinesh Subhraveti | { |
533 | ef74679a | Dinesh Subhraveti | PS2KbdState *s = (PS2KbdState *) opaque; |
534 | ef74679a | Dinesh Subhraveti | |
535 | ef74679a | Dinesh Subhraveti | ps2_common_reset(&s->common); |
536 | ef74679a | Dinesh Subhraveti | s->scan_enabled = 0;
|
537 | ef74679a | Dinesh Subhraveti | s->translate = 0;
|
538 | ef74679a | Dinesh Subhraveti | s->scancode_set = 0;
|
539 | ef74679a | Dinesh Subhraveti | } |
540 | ef74679a | Dinesh Subhraveti | |
541 | ef74679a | Dinesh Subhraveti | static void ps2_mouse_reset(void *opaque) |
542 | ef74679a | Dinesh Subhraveti | { |
543 | ef74679a | Dinesh Subhraveti | PS2MouseState *s = (PS2MouseState *) opaque; |
544 | ef74679a | Dinesh Subhraveti | |
545 | ef74679a | Dinesh Subhraveti | ps2_common_reset(&s->common); |
546 | ef74679a | Dinesh Subhraveti | s->mouse_status = 0;
|
547 | ef74679a | Dinesh Subhraveti | s->mouse_resolution = 0;
|
548 | ef74679a | Dinesh Subhraveti | s->mouse_sample_rate = 0;
|
549 | ef74679a | Dinesh Subhraveti | s->mouse_wrap = 0;
|
550 | ef74679a | Dinesh Subhraveti | s->mouse_type = 0;
|
551 | ef74679a | Dinesh Subhraveti | s->mouse_detect_state = 0;
|
552 | ef74679a | Dinesh Subhraveti | s->mouse_dx = 0;
|
553 | ef74679a | Dinesh Subhraveti | s->mouse_dy = 0;
|
554 | ef74679a | Dinesh Subhraveti | s->mouse_dz = 0;
|
555 | ef74679a | Dinesh Subhraveti | s->mouse_buttons = 0;
|
556 | ef74679a | Dinesh Subhraveti | } |
557 | ef74679a | Dinesh Subhraveti | |
558 | b31442c3 | Juan Quintela | static const VMStateDescription vmstate_ps2_common = { |
559 | b31442c3 | Juan Quintela | .name = "PS2 Common State",
|
560 | b31442c3 | Juan Quintela | .version_id = 3,
|
561 | b31442c3 | Juan Quintela | .minimum_version_id = 2,
|
562 | b31442c3 | Juan Quintela | .minimum_version_id_old = 2,
|
563 | b31442c3 | Juan Quintela | .fields = (VMStateField []) { |
564 | b31442c3 | Juan Quintela | VMSTATE_INT32(write_cmd, PS2State), |
565 | b31442c3 | Juan Quintela | VMSTATE_INT32(queue.rptr, PS2State), |
566 | b31442c3 | Juan Quintela | VMSTATE_INT32(queue.wptr, PS2State), |
567 | b31442c3 | Juan Quintela | VMSTATE_INT32(queue.count, PS2State), |
568 | b31442c3 | Juan Quintela | VMSTATE_BUFFER(queue.data, PS2State), |
569 | b31442c3 | Juan Quintela | VMSTATE_END_OF_LIST() |
570 | b31442c3 | Juan Quintela | } |
571 | b31442c3 | Juan Quintela | }; |
572 | 0e43e99c | bellard | |
573 | 7f540ab5 | Christophe Fergeau | static bool ps2_keyboard_ledstate_needed(void *opaque) |
574 | 7f540ab5 | Christophe Fergeau | { |
575 | 7f540ab5 | Christophe Fergeau | PS2KbdState *s = opaque; |
576 | 7f540ab5 | Christophe Fergeau | |
577 | 7f540ab5 | Christophe Fergeau | return s->ledstate != 0; /* 0 is default state */ |
578 | 7f540ab5 | Christophe Fergeau | } |
579 | 7f540ab5 | Christophe Fergeau | |
580 | 7f540ab5 | Christophe Fergeau | static int ps2_kbd_ledstate_post_load(void *opaque, int version_id) |
581 | 7f540ab5 | Christophe Fergeau | { |
582 | 7f540ab5 | Christophe Fergeau | PS2KbdState *s = opaque; |
583 | 7f540ab5 | Christophe Fergeau | |
584 | 7f540ab5 | Christophe Fergeau | kbd_put_ledstate(s->ledstate); |
585 | 7f540ab5 | Christophe Fergeau | return 0; |
586 | 7f540ab5 | Christophe Fergeau | } |
587 | 7f540ab5 | Christophe Fergeau | |
588 | 7f540ab5 | Christophe Fergeau | static const VMStateDescription vmstate_ps2_keyboard_ledstate = { |
589 | 7f540ab5 | Christophe Fergeau | .name = "ps2kbd/ledstate",
|
590 | 7f540ab5 | Christophe Fergeau | .version_id = 3,
|
591 | 7f540ab5 | Christophe Fergeau | .minimum_version_id = 2,
|
592 | 7f540ab5 | Christophe Fergeau | .minimum_version_id_old = 2,
|
593 | 7f540ab5 | Christophe Fergeau | .post_load = ps2_kbd_ledstate_post_load, |
594 | 7f540ab5 | Christophe Fergeau | .fields = (VMStateField []) { |
595 | 7f540ab5 | Christophe Fergeau | VMSTATE_INT32(ledstate, PS2KbdState), |
596 | 7f540ab5 | Christophe Fergeau | VMSTATE_END_OF_LIST() |
597 | 7f540ab5 | Christophe Fergeau | } |
598 | 7f540ab5 | Christophe Fergeau | }; |
599 | 7f540ab5 | Christophe Fergeau | |
600 | db596c53 | Juan Quintela | static int ps2_kbd_post_load(void* opaque, int version_id) |
601 | 0e43e99c | bellard | { |
602 | 0e43e99c | bellard | PS2KbdState *s = (PS2KbdState*)opaque; |
603 | 7783e9f0 | pbrook | |
604 | db596c53 | Juan Quintela | if (version_id == 2) |
605 | e7d93956 | aurel32 | s->scancode_set=2;
|
606 | 0e43e99c | bellard | return 0; |
607 | 0e43e99c | bellard | } |
608 | 0e43e99c | bellard | |
609 | b31442c3 | Juan Quintela | static const VMStateDescription vmstate_ps2_keyboard = { |
610 | b31442c3 | Juan Quintela | .name = "ps2kbd",
|
611 | b31442c3 | Juan Quintela | .version_id = 3,
|
612 | db596c53 | Juan Quintela | .minimum_version_id = 2,
|
613 | b31442c3 | Juan Quintela | .minimum_version_id_old = 2,
|
614 | db596c53 | Juan Quintela | .post_load = ps2_kbd_post_load, |
615 | b31442c3 | Juan Quintela | .fields = (VMStateField []) { |
616 | b31442c3 | Juan Quintela | VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
|
617 | b31442c3 | Juan Quintela | VMSTATE_INT32(scan_enabled, PS2KbdState), |
618 | b31442c3 | Juan Quintela | VMSTATE_INT32(translate, PS2KbdState), |
619 | b31442c3 | Juan Quintela | VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
|
620 | b31442c3 | Juan Quintela | VMSTATE_END_OF_LIST() |
621 | 7f540ab5 | Christophe Fergeau | }, |
622 | 7f540ab5 | Christophe Fergeau | .subsections = (VMStateSubsection []) { |
623 | 7f540ab5 | Christophe Fergeau | { |
624 | 7f540ab5 | Christophe Fergeau | .vmsd = &vmstate_ps2_keyboard_ledstate, |
625 | 7f540ab5 | Christophe Fergeau | .needed = ps2_keyboard_ledstate_needed, |
626 | 7f540ab5 | Christophe Fergeau | }, { |
627 | 7f540ab5 | Christophe Fergeau | /* empty */
|
628 | 7f540ab5 | Christophe Fergeau | } |
629 | b31442c3 | Juan Quintela | } |
630 | b31442c3 | Juan Quintela | }; |
631 | 7783e9f0 | pbrook | |
632 | b31442c3 | Juan Quintela | static const VMStateDescription vmstate_ps2_mouse = { |
633 | b31442c3 | Juan Quintela | .name = "ps2mouse",
|
634 | b31442c3 | Juan Quintela | .version_id = 2,
|
635 | b31442c3 | Juan Quintela | .minimum_version_id = 2,
|
636 | b31442c3 | Juan Quintela | .minimum_version_id_old = 2,
|
637 | b31442c3 | Juan Quintela | .fields = (VMStateField []) { |
638 | b31442c3 | Juan Quintela | VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
|
639 | b31442c3 | Juan Quintela | VMSTATE_UINT8(mouse_status, PS2MouseState), |
640 | b31442c3 | Juan Quintela | VMSTATE_UINT8(mouse_resolution, PS2MouseState), |
641 | b31442c3 | Juan Quintela | VMSTATE_UINT8(mouse_sample_rate, PS2MouseState), |
642 | b31442c3 | Juan Quintela | VMSTATE_UINT8(mouse_wrap, PS2MouseState), |
643 | b31442c3 | Juan Quintela | VMSTATE_UINT8(mouse_type, PS2MouseState), |
644 | b31442c3 | Juan Quintela | VMSTATE_UINT8(mouse_detect_state, PS2MouseState), |
645 | b31442c3 | Juan Quintela | VMSTATE_INT32(mouse_dx, PS2MouseState), |
646 | b31442c3 | Juan Quintela | VMSTATE_INT32(mouse_dy, PS2MouseState), |
647 | b31442c3 | Juan Quintela | VMSTATE_INT32(mouse_dz, PS2MouseState), |
648 | b31442c3 | Juan Quintela | VMSTATE_UINT8(mouse_buttons, PS2MouseState), |
649 | b31442c3 | Juan Quintela | VMSTATE_END_OF_LIST() |
650 | b31442c3 | Juan Quintela | } |
651 | b31442c3 | Juan Quintela | }; |
652 | 0e43e99c | bellard | |
653 | 0e43e99c | bellard | void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) |
654 | 0e43e99c | bellard | { |
655 | 7267c094 | Anthony Liguori | PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
|
656 | 0e43e99c | bellard | |
657 | 0e43e99c | bellard | s->common.update_irq = update_irq; |
658 | 0e43e99c | bellard | s->common.update_arg = update_arg; |
659 | e7d93956 | aurel32 | s->scancode_set = 2;
|
660 | 0be71e32 | Alex Williamson | vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s); |
661 | 0e43e99c | bellard | qemu_add_kbd_event_handler(ps2_put_keycode, s); |
662 | ef74679a | Dinesh Subhraveti | qemu_register_reset(ps2_kbd_reset, s); |
663 | 0e43e99c | bellard | return s;
|
664 | 0e43e99c | bellard | } |
665 | 0e43e99c | bellard | |
666 | 0e43e99c | bellard | void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) |
667 | 0e43e99c | bellard | { |
668 | 7267c094 | Anthony Liguori | PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
|
669 | 0e43e99c | bellard | |
670 | 0e43e99c | bellard | s->common.update_irq = update_irq; |
671 | 0e43e99c | bellard | s->common.update_arg = update_arg; |
672 | 0be71e32 | Alex Williamson | vmstate_register(NULL, 0, &vmstate_ps2_mouse, s); |
673 | 455204eb | ths | qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse"); |
674 | ef74679a | Dinesh Subhraveti | qemu_register_reset(ps2_mouse_reset, s); |
675 | 0e43e99c | bellard | return s;
|
676 | 0e43e99c | bellard | } |