ia64/xen-unstable

view tools/ioemu/hw/pckbd.c @ 6512:e5ea9df58340

Fix Mouse hang with VNC

I've made some progress on this problem. Turns out, the VNC emulator is
a little over aggressive in dealing with reset commands for the mouse.
Since there are commands that enable and disable the mouse the VNC
emulator provides this control. Unfortunately, VNC also interprets
either a `reset' or `set to default' command to also disable the mouse.
This is wrong, neither of these commands are supposed to affect the
enabled status of the mouse so that, when X sends a `reset', no futher
mouse data is sent, making it look like X is hung.

Signed-off-by: Don Dugger <donald.d.dugger@intel.com>
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
author adsharma@los-vmm.sc.intel.com
date Tue Aug 09 11:06:44 2005 -0800 (2005-08-09)
parents 8e5fc5fe636c
children 3d31c0ecdbd8
line source
1 /*
2 * QEMU PC keyboard emulation
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 #include "vl.h"
26 /* debug PC keyboard */
27 //#define DEBUG_KBD
29 /* debug PC keyboard : only mouse */
30 //#define DEBUG_MOUSE
32 /* Keyboard Controller Commands */
33 #define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
34 #define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */
35 #define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */
36 #define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */
37 #define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */
38 #define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */
39 #define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */
40 #define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */
41 #define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */
42 #define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */
43 #define KBD_CCMD_READ_INPORT 0xC0 /* read input port */
44 #define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */
45 #define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */
46 #define KBD_CCMD_WRITE_OBUF 0xD2
47 #define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if
48 initiated by the auxiliary device */
49 #define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */
50 #define KBD_CCMD_DISABLE_A20 0xDD /* HP vectra only ? */
51 #define KBD_CCMD_ENABLE_A20 0xDF /* HP vectra only ? */
52 #define KBD_CCMD_RESET 0xFE
54 /* Keyboard Commands */
55 #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
56 #define KBD_CMD_ECHO 0xEE
57 #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
58 #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
59 #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
60 #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
61 #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
62 #define KBD_CMD_RESET 0xFF /* Reset */
64 /* Keyboard Replies */
65 #define KBD_REPLY_POR 0xAA /* Power on reset */
66 #define KBD_REPLY_ACK 0xFA /* Command ACK */
67 #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
69 /* Status Register Bits */
70 #define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
71 #define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
72 #define KBD_STAT_SELFTEST 0x04 /* Self test successful */
73 #define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
74 #define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
75 #define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
76 #define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
77 #define KBD_STAT_PERR 0x80 /* Parity error */
79 /* Controller Mode Register Bits */
80 #define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */
81 #define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */
82 #define KBD_MODE_SYS 0x04 /* The system flag (?) */
83 #define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */
84 #define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */
85 #define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */
86 #define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */
87 #define KBD_MODE_RFU 0x80
89 /* Mouse Commands */
90 #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
91 #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
92 #define AUX_SET_RES 0xE8 /* Set resolution */
93 #define AUX_GET_SCALE 0xE9 /* Get scaling factor */
94 /* according to Synaptic docs this $E9 is really 3-byte status */
95 #define AUX_SET_STREAM 0xEA /* Set stream mode */
96 #define AUX_POLL 0xEB /* Poll */
97 #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
98 #define AUX_SET_WRAP 0xEE /* Set wrap mode */
99 #define AUX_SET_REMOTE 0xF0 /* Set remote mode */
100 #define AUX_GET_TYPE 0xF2 /* Get type */
101 #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
102 #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
103 #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
104 #define AUX_SET_DEFAULT 0xF6
105 #define AUX_RESET 0xFF /* Reset aux device */
106 #define AUX_ACK 0xFA /* Command byte ACK. */
108 #define MOUSE_STATUS_REMOTE 0x40
109 #define MOUSE_STATUS_ENABLED 0x20
110 #define MOUSE_STATUS_SCALE21 0x10
112 #define KBD_QUEUE_SIZE 256
114 typedef struct {
115 uint8_t aux[KBD_QUEUE_SIZE];
116 uint8_t data[KBD_QUEUE_SIZE];
117 int rptr, wptr, count;
118 } KBDQueue;
120 typedef struct {
121 int absolute;
122 int high;
123 } TouchPad;
125 typedef struct KBDState {
126 KBDQueue queue;
127 uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
128 uint8_t status;
129 uint8_t mode;
130 /* keyboard state */
131 int kbd_write_cmd;
132 int scan_enabled;
133 /* mouse state */
134 int mouse_write_cmd;
135 uint8_t mouse_status;
136 uint8_t mouse_resolution;
137 uint8_t mouse_sample_rate;
138 uint8_t mouse_wrap;
139 uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
140 uint8_t mouse_detect_state;
141 int mouse_dx; /* current values, needed for 'poll' mode */
142 int mouse_dy;
143 int mouse_dz;
144 uint8_t mouse_buttons;
145 TouchPad touchpad;
146 } KBDState;
148 KBDState kbd_state;
150 /* update irq and KBD_STAT_[MOUSE_]OBF */
151 /* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
152 incorrect, but it avoids having to simulate exact delays */
153 static void kbd_update_irq(KBDState *s)
154 {
155 KBDQueue *q = &s->queue;
156 int irq12_level, irq1_level;
158 irq1_level = 0;
159 irq12_level = 0;
160 s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
161 if (q->count != 0) {
162 s->status |= KBD_STAT_OBF;
163 if (q->aux[q->rptr]) {
164 s->status |= KBD_STAT_MOUSE_OBF;
165 if (s->mode & KBD_MODE_MOUSE_INT)
166 irq12_level = 1;
167 } else {
168 if ((s->mode & KBD_MODE_KBD_INT) &&
169 !(s->mode & KBD_MODE_DISABLE_KBD))
170 irq1_level = 1;
171 }
172 }
173 pic_set_irq(1, irq1_level);
174 pic_set_irq(12, irq12_level);
175 }
177 static void kbd_queue(KBDState *s, int b, int aux)
178 {
179 KBDQueue *q = &s->queue;
181 #if defined(DEBUG_MOUSE) || defined(DEBUG_KBD)
182 if (aux)
183 printf("mouse event: 0x%02x\n", b);
184 #ifdef DEBUG_KBD
185 else
186 printf("kbd event: 0x%02x\n", b);
187 #endif
188 #endif
189 if (q->count >= KBD_QUEUE_SIZE)
190 return;
191 q->aux[q->wptr] = aux;
192 q->data[q->wptr] = b;
193 if (++q->wptr == KBD_QUEUE_SIZE)
194 q->wptr = 0;
195 q->count++;
196 kbd_update_irq(s);
197 }
199 static void pc_kbd_put_keycode(void *opaque, int keycode)
200 {
201 KBDState *s = opaque;
202 kbd_queue(s, keycode, 0);
203 }
205 static uint32_t kbd_read_status(void *opaque, uint32_t addr)
206 {
207 KBDState *s = opaque;
208 int val;
209 val = s->status;
210 #if defined(DEBUG_KBD)
211 printf("kbd: read status=0x%02x\n", val);
212 #endif
213 return val;
214 }
216 static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
217 {
218 KBDState *s = opaque;
220 #ifdef DEBUG_KBD
221 printf("kbd: write cmd=0x%02x\n", val);
222 #endif
223 switch(val) {
224 case KBD_CCMD_READ_MODE:
225 kbd_queue(s, s->mode, 0);
226 break;
227 case KBD_CCMD_WRITE_MODE:
228 case KBD_CCMD_WRITE_OBUF:
229 case KBD_CCMD_WRITE_AUX_OBUF:
230 case KBD_CCMD_WRITE_MOUSE:
231 case KBD_CCMD_WRITE_OUTPORT:
232 s->write_cmd = val;
233 break;
234 case KBD_CCMD_MOUSE_DISABLE:
235 s->mode |= KBD_MODE_DISABLE_MOUSE;
236 break;
237 case KBD_CCMD_MOUSE_ENABLE:
238 s->mode &= ~KBD_MODE_DISABLE_MOUSE;
239 break;
240 case KBD_CCMD_TEST_MOUSE:
241 kbd_queue(s, 0x00, 0);
242 break;
243 case KBD_CCMD_SELF_TEST:
244 s->status |= KBD_STAT_SELFTEST;
245 kbd_queue(s, 0x55, 0);
246 break;
247 case KBD_CCMD_KBD_TEST:
248 kbd_queue(s, 0x00, 0);
249 break;
250 case KBD_CCMD_KBD_DISABLE:
251 s->mode |= KBD_MODE_DISABLE_KBD;
252 kbd_update_irq(s);
253 break;
254 case KBD_CCMD_KBD_ENABLE:
255 s->mode &= ~KBD_MODE_DISABLE_KBD;
256 kbd_update_irq(s);
257 break;
258 case KBD_CCMD_READ_INPORT:
259 kbd_queue(s, 0x00, 0);
260 break;
261 case KBD_CCMD_READ_OUTPORT:
262 /* XXX: check that */
263 #ifdef TARGET_I386
264 val = 0x01 | (((cpu_single_env->a20_mask >> 20) & 1) << 1);
265 #else
266 val = 0x01;
267 #endif
268 if (s->status & KBD_STAT_OBF)
269 val |= 0x10;
270 if (s->status & KBD_STAT_MOUSE_OBF)
271 val |= 0x20;
272 kbd_queue(s, val, 0);
273 break;
274 #ifdef TARGET_I386
275 case KBD_CCMD_ENABLE_A20:
276 cpu_x86_set_a20(cpu_single_env, 1);
277 break;
278 case KBD_CCMD_DISABLE_A20:
279 cpu_x86_set_a20(cpu_single_env, 0);
280 break;
281 #endif
282 case KBD_CCMD_RESET:
283 qemu_system_reset_request();
284 break;
285 case 0xff:
286 /* ignore that - I don't know what is its use */
287 break;
288 default:
289 fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val);
290 break;
291 }
292 }
294 static uint32_t kbd_read_data(void *opaque, uint32_t addr)
295 {
296 KBDState *s = opaque;
297 KBDQueue *q;
298 int val, index, aux;
300 q = &s->queue;
301 if (q->count == 0) {
302 /* NOTE: if no data left, we return the last keyboard one
303 (needed for EMM386) */
304 /* XXX: need a timer to do things correctly */
305 index = q->rptr - 1;
306 if (index < 0)
307 index = KBD_QUEUE_SIZE - 1;
308 val = q->data[index];
309 } else {
310 aux = q->aux[q->rptr];
311 val = q->data[q->rptr];
312 if (++q->rptr == KBD_QUEUE_SIZE)
313 q->rptr = 0;
314 q->count--;
315 /* reading deasserts IRQ */
316 if (aux)
317 pic_set_irq(12, 0);
318 else
319 pic_set_irq(1, 0);
320 }
321 /* reassert IRQs if data left */
322 kbd_update_irq(s);
323 #ifdef DEBUG_KBD
324 printf("kbd: read data=0x%02x\n", val);
325 #endif
326 return val;
327 }
329 static void kbd_reset_keyboard(KBDState *s)
330 {
331 s->scan_enabled = 1;
332 }
334 static void kbd_write_keyboard(KBDState *s, int val)
335 {
336 switch(s->kbd_write_cmd) {
337 default:
338 case -1:
339 switch(val) {
340 case 0x00:
341 kbd_queue(s, KBD_REPLY_ACK, 0);
342 break;
343 case 0x05:
344 kbd_queue(s, KBD_REPLY_RESEND, 0);
345 break;
346 case KBD_CMD_GET_ID:
347 kbd_queue(s, KBD_REPLY_ACK, 0);
348 kbd_queue(s, 0xab, 0);
349 kbd_queue(s, 0x83, 0);
350 break;
351 case KBD_CMD_ECHO:
352 kbd_queue(s, KBD_CMD_ECHO, 0);
353 break;
354 case KBD_CMD_ENABLE:
355 s->scan_enabled = 1;
356 kbd_queue(s, KBD_REPLY_ACK, 0);
357 break;
358 case KBD_CMD_SET_LEDS:
359 case KBD_CMD_SET_RATE:
360 s->kbd_write_cmd = val;
361 kbd_queue(s, KBD_REPLY_ACK, 0);
362 break;
363 case KBD_CMD_RESET_DISABLE:
364 kbd_reset_keyboard(s);
365 s->scan_enabled = 0;
366 kbd_queue(s, KBD_REPLY_ACK, 0);
367 break;
368 case KBD_CMD_RESET_ENABLE:
369 kbd_reset_keyboard(s);
370 s->scan_enabled = 1;
371 kbd_queue(s, KBD_REPLY_ACK, 0);
372 break;
373 case KBD_CMD_RESET:
374 kbd_reset_keyboard(s);
375 kbd_queue(s, KBD_REPLY_ACK, 0);
376 kbd_queue(s, KBD_REPLY_POR, 0);
377 break;
378 default:
379 kbd_queue(s, KBD_REPLY_ACK, 0);
380 break;
381 }
382 break;
383 case KBD_CMD_SET_LEDS:
384 kbd_queue(s, KBD_REPLY_ACK, 0);
385 s->kbd_write_cmd = -1;
386 break;
387 case KBD_CMD_SET_RATE:
388 kbd_queue(s, KBD_REPLY_ACK, 0);
389 s->kbd_write_cmd = -1;
390 break;
391 }
392 }
394 static void kbd_mouse_send_packet(KBDState *s)
395 {
396 unsigned int b;
397 int dx1, dy1, dz1;
399 dx1 = s->mouse_dx;
400 dy1 = s->mouse_dy;
401 dz1 = s->mouse_dz;
402 if (s->touchpad.absolute)
403 {
404 int dz2, dleftnright, dg, df;
405 if (dx1 > 6143)
406 dx1 = 6143;
407 else if (dx1 < 0)
408 dx1 = 0;
409 if (dy1 > 6143)
410 dy1 = 6143;
411 else if (dy1 < 0)
412 dy1 = 0;
413 dz2 = 80; /* normal finger pressure */
414 dg = 0; /* guesture not supported */
415 df = 0; /* finger not supported */
416 dleftnright = (s->mouse_buttons & 0x07);
417 /*
418 X: 13 bits --return absolute x ord
419 Y: 13 bits --return absolute y ord
420 Z: 8 bits --return constant 80 since we don't know how hard the user
421 is pressing on the mouse button ;) 80 is the default for pen
422 pressure, as touchpads cant sense what pressure a pen makes.
423 W: 4 bits --return 0, we don't support finger width (should we?)
424 left: 1 bit --is left button pressed
425 right: 1 bit --is right button pressed
426 guesture: 1 bit --we dont support, return 0
427 finger: 1 bit --ditto
428 total: 42 bits in 6 bytes
429 note that Synaptics drivers ignore the finger and guesture bits and
430 consider them redundant
431 */
432 /*
433 note: the packet setup is different when Wmode = 1, but
434 this doesn't apply since we don't support Wmode capability
435 format of packet is as follows:
436 */
437 // 1 0 finger reserved 0 gesture right left
438 kbd_queue(s, (0x80 | (df ? 0x20 : 0) | (dg ? 0x04 : 0) | dleftnright), 1);
439 kbd_queue(s, ((dy1 & 0xF) * 256) + (dx1 & 0xF), 1);
440 kbd_queue(s, 80, 1); //byte 3
441 // 1 1 y-12 x-12 0 gesture right left
442 kbd_queue(s, (0xC0 | ((dy1 & 1000) ? 0x20 : 0) | ((dx1 & 1000) ? 0x10 : 0) | (dg ? 0x04 : 0) | dleftnright), 1);
443 kbd_queue(s, dx1 & 0xFF, 1);
444 kbd_queue(s, dy1 & 0xFF, 1);
445 return;
446 }
447 /* XXX: increase range to 8 bits ? */
448 if (dx1 > 127)
449 dx1 = 127;
450 else if (dx1 < -127)
451 dx1 = -127;
452 if (dy1 > 127)
453 dy1 = 127;
454 else if (dy1 < -127)
455 dy1 = -127;
456 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
457 kbd_queue(s, b, 1);
458 kbd_queue(s, dx1 & 0xff, 1);
459 kbd_queue(s, dy1 & 0xff, 1);
460 /* extra byte for IMPS/2 or IMEX */
461 switch(s->mouse_type) {
462 default:
463 break;
464 case 3:
465 if (dz1 > 127)
466 dz1 = 127;
467 else if (dz1 < -127)
468 dz1 = -127;
469 kbd_queue(s, dz1 & 0xff, 1);
470 break;
471 case 4:
472 if (dz1 > 7)
473 dz1 = 7;
474 else if (dz1 < -7)
475 dz1 = -7;
476 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
477 kbd_queue(s, b, 1);
478 break;
479 }
481 /* update deltas */
482 s->mouse_dx -= dx1;
483 s->mouse_dy -= dy1;
484 s->mouse_dz -= dz1;
485 }
487 static void pc_kbd_mouse_event(void *opaque,
488 int dx, int dy, int dz, int buttons_state)
489 {
490 KBDState *s = opaque;
492 /* check if deltas are recorded when disabled */
493 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
494 return;
496 s->mouse_dx += dx;
497 s->mouse_dy -= dy;
498 s->mouse_dz += dz;
499 /* XXX: SDL sometimes generates nul events: we delete them */
500 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
501 s->mouse_buttons == buttons_state)
502 return;
503 s->mouse_buttons = buttons_state;
505 if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
506 (s->queue.count < (KBD_QUEUE_SIZE - 16))) {
507 for(;;) {
508 /* if not remote, send event. Multiple events are sent if
509 too big deltas */
510 kbd_mouse_send_packet(s);
511 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
512 break;
513 }
514 }
515 }
517 static void kbd_write_mouse(KBDState *s, int val)
518 {
519 /* variables needed to store synaptics command info */
520 static int rr = 0, ss = 0, tt = 0, uu = 0, res_count = 0, last_com = 0;
521 int spare;
522 #ifdef DEBUG_MOUSE
523 printf("kbd: write mouse 0x%02x\n", val);
524 #endif
525 switch(s->mouse_write_cmd) {
526 default:
527 case -1:
528 /* mouse command */
529 if (s->mouse_wrap) {
530 if (val == AUX_RESET_WRAP) {
531 s->mouse_wrap = 0;
532 kbd_queue(s, AUX_ACK, 1);
533 return;
534 } else if (val != AUX_RESET) {
535 kbd_queue(s, val, 1);
536 return;
537 }
538 }
539 last_com = val;
540 switch(val) {
541 case AUX_SET_SCALE11:
542 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
543 kbd_queue(s, AUX_ACK, 1);
544 break;
545 case AUX_SET_SCALE21:
546 s->mouse_status |= MOUSE_STATUS_SCALE21;
547 kbd_queue(s, AUX_ACK, 1);
548 break;
549 case AUX_SET_STREAM:
550 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
551 kbd_queue(s, AUX_ACK, 1);
552 break;
553 case AUX_SET_WRAP:
554 s->mouse_wrap = 1;
555 kbd_queue(s, AUX_ACK, 1);
556 break;
557 case AUX_SET_REMOTE:
558 s->mouse_status |= MOUSE_STATUS_REMOTE;
559 kbd_queue(s, AUX_ACK, 1);
560 break;
561 case AUX_GET_TYPE:
562 kbd_queue(s, AUX_ACK, 1);
563 kbd_queue(s, s->mouse_type, 1);
564 break;
565 case AUX_SET_RES:
566 case AUX_SET_SAMPLE:
567 s->mouse_write_cmd = val;
568 kbd_queue(s, AUX_ACK, 1);
569 break;
570 case AUX_GET_SCALE:
571 if (res_count == 4)
572 {
573 /* time for the special stuff */
574 kbd_queue(s, AUX_ACK, 1);
575 /* below is how we get the real synaptic command */
576 val = (rr*64) + (ss*16) + (tt*4) + uu;
577 switch(val)
578 {
579 /* id touchpad */
580 case 0x00:
581 /* info Minor */
582 kbd_queue(s, 0x00, 1);
583 /* special verification byte */
584 kbd_queue(s, 0x47, 1);
585 /* info Major * 0x10 + Info ModelCode*/
586 kbd_queue(s, 4 * 0x10 + 0, 1);
587 break;
588 /* read touchpad modes */
589 case 0x01:
590 /* special verification byte */
591 kbd_queue(s, 0x3B, 1);
592 /* mode */
593 /*
594 bit 7 - absolute or relative position
595 bit 6 - 0 for 40 packets/sec, 1 for 80 pack/sec
596 bit 3 - 1 for sleep mode, 0 for normal
597 bit 2 - 1 to detect tap/drag, 0 to disable
598 bit 1 - packet size, only valid for serial protocol
599 bit 0 - 0 for normal packets, 1 for enhanced packets
600 (absolute mode packets which have finger width)
601 */
602 if (s->touchpad.absolute && s->touchpad.high)
603 {
604 spare = 0xC0;
605 }
606 else if (s->touchpad.absolute)
607 {
608 spare = 0x80;
609 }
610 else if (s->touchpad.high)
611 {
612 spare = 0x40;
613 }
614 else
615 {
616 spare = 0x00;
617 }
618 kbd_queue(s, spare, 1);
619 /* special verification byte */
620 kbd_queue(s, 0x47, 1);
621 break;
622 /* read touchpad capabilites */
623 case 0x02:
624 /* extended capability first 8 bits */
625 kbd_queue(s, 0x00, 1);
626 /* special verification byte */
627 kbd_queue(s, 0x47, 1);
628 /* extended capability last 8 bits */
629 kbd_queue(s, 0x00, 1);
630 /* basicly, we don't have any capabilites ;0 */
631 break;
632 /* read model id */
633 case 0x03:
634 /*
635 bit 23 = 0 (1 for upsidedownpad)
636 bit 22 = 0 (1 for 90 degree rotated pad)
637 bits 21-16 = 1 (standard model)
638 bits 15-9 = ??? (reserved for synaptics use)
639 bit 7 = 1
640 bit 6 = 0 (1 for sensing pens)
641 bit 5 = 1
642 bits 3-0 = 1 (rectangular geometery)
643 */
644 kbd_queue(s, 0xFC, 1);
645 kbd_queue(s, 0x00, 1);
646 kbd_queue(s, 0xF5, 1); //F7 for sensing pens
647 break;
648 /* read serial number prefix */
649 case 0x06:
650 /* strange how they have this query even though
651 no touchpad actually has serial numbers */
652 /* return serial prefix of 0 if we dont have one */
653 kbd_queue(s, 0x00, 1);
654 kbd_queue(s, 0x00, 1);
655 kbd_queue(s, 0x00, 1);
656 break;
657 /* read serial number suffix */
658 case 0x07:
659 /* undefined if we dont have a valid serial prefix */
660 kbd_queue(s, 0x00, 1);
661 kbd_queue(s, 0x00, 1);
662 kbd_queue(s, 0x00, 1);
663 break;
664 /* read resolutions */
665 case 0x08:
666 /* going to go with infoSensor = 1 (Standard model) here */
667 /* absolute X in abolute units per mm */
668 kbd_queue(s, 85, 1);
669 /* undefined but first bit 7 will be set to 1...
670 hell I'm going to set them all to 1 */
671 kbd_queue(s, 0xFF, 1);
672 /* absolute Y in abolute units per mm */
673 kbd_queue(s, 94, 1);
674 break;
675 default:
676 /* invalid commands return undefined data */
677 kbd_queue(s, 0x00, 1);
678 kbd_queue(s, 0x00, 1);
679 kbd_queue(s, 0x00, 1);
680 break;
681 }
682 }
683 else
684 {
685 /* not a special command, just do the regular stuff */
686 kbd_queue(s, AUX_ACK, 1);
687 kbd_queue(s, s->mouse_status, 1);
688 kbd_queue(s, s->mouse_resolution, 1);
689 kbd_queue(s, s->mouse_sample_rate, 1);
690 }
691 break;
692 case AUX_POLL:
693 kbd_queue(s, AUX_ACK, 1);
694 kbd_mouse_send_packet(s);
695 break;
696 case AUX_ENABLE_DEV:
697 s->mouse_status |= MOUSE_STATUS_ENABLED;
698 kbd_queue(s, AUX_ACK, 1);
699 break;
700 case AUX_DISABLE_DEV:
701 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
702 kbd_queue(s, AUX_ACK, 1);
703 break;
704 case AUX_SET_DEFAULT:
705 s->mouse_sample_rate = 100;
706 s->mouse_resolution = 2;
707 s->mouse_status &= MOUSE_STATUS_ENABLED;
708 s->touchpad.absolute = 0;
709 kbd_queue(s, AUX_ACK, 1);
710 break;
711 case AUX_RESET:
712 s->mouse_sample_rate = 100;
713 s->mouse_resolution = 2;
714 s->mouse_status &= MOUSE_STATUS_ENABLED;
715 s->touchpad.absolute = 0;
716 kbd_queue(s, AUX_ACK, 1);
717 kbd_queue(s, 0xaa, 1);
718 kbd_queue(s, s->mouse_type, 1);
719 break;
720 default:
721 break;
722 }
723 break;
724 case AUX_SET_SAMPLE:
725 if (res_count == 4 && val == 0x14)
726 {
727 /* time for the special stuff */
728 /* below is how we get the real synaptic command */
729 val = (rr*64) + (ss*16) + (tt*4) + uu;
730 /* TODO: set the mode byte */
731 } else
732 s->mouse_sample_rate = val;
733 #if 0
734 /* detect IMPS/2 or IMEX */
735 switch(s->mouse_detect_state) {
736 default:
737 case 0:
738 if (val == 200)
739 s->mouse_detect_state = 1;
740 break;
741 case 1:
742 if (val == 100)
743 s->mouse_detect_state = 2;
744 else if (val == 200)
745 s->mouse_detect_state = 3;
746 else
747 s->mouse_detect_state = 0;
748 break;
749 case 2:
750 if (val == 80)
751 s->mouse_type = 3; /* IMPS/2 */
752 s->mouse_detect_state = 0;
753 break;
754 case 3:
755 if (val == 80)
756 s->mouse_type = 4; /* IMEX */
757 s->mouse_detect_state = 0;
758 break;
759 }
760 #endif
761 kbd_queue(s, AUX_ACK, 1);
762 s->mouse_write_cmd = -1;
763 break;
764 case AUX_SET_RES:
765 if (last_com != AUX_SET_RES)
766 {
767 /* if its not 4 in a row, its not a command */
768 /* FIXME: if we are set 8 of these in a row, or 12, or 16,
769 or etc ... or 4^n commands, then the nth'd mode byte sent might
770 still work. not sure if this is how things are suppose to be
771 or not. */
772 res_count = 0;
773 }
774 res_count++;
775 if (res_count > 4) res_count = 4;
776 switch(res_count)
777 /* we need to save the val in the right spots to get the
778 real command later */
779 {
780 case 1:
781 break;
782 rr = val;
783 case 2:
784 ss = val;
785 break;
786 case 3:
787 tt = val;
788 break;
789 case 4:
790 uu = val;
791 break;
792 }
793 s->mouse_resolution = val;
794 kbd_queue(s, AUX_ACK, 1);
795 s->mouse_write_cmd = -1;
796 break;
797 }
798 }
800 void kbd_write_data(void *opaque, uint32_t addr, uint32_t val)
801 {
802 KBDState *s = opaque;
804 #ifdef DEBUG_KBD
805 printf("kbd: write data=0x%02x\n", val);
806 #endif
808 switch(s->write_cmd) {
809 case 0:
810 kbd_write_keyboard(s, val);
811 break;
812 case KBD_CCMD_WRITE_MODE:
813 s->mode = val;
814 kbd_update_irq(s);
815 break;
816 case KBD_CCMD_WRITE_OBUF:
817 kbd_queue(s, val, 0);
818 break;
819 case KBD_CCMD_WRITE_AUX_OBUF:
820 kbd_queue(s, val, 1);
821 break;
822 case KBD_CCMD_WRITE_OUTPORT:
823 #ifdef TARGET_I386
824 cpu_x86_set_a20(cpu_single_env, (val >> 1) & 1);
825 #endif
826 if (!(val & 1)) {
827 qemu_system_reset_request();
828 }
829 break;
830 case KBD_CCMD_WRITE_MOUSE:
831 kbd_write_mouse(s, val);
832 break;
833 default:
834 break;
835 }
836 s->write_cmd = 0;
837 }
839 static void kbd_reset(void *opaque)
840 {
841 KBDState *s = opaque;
842 KBDQueue *q;
844 s->kbd_write_cmd = -1;
845 s->mouse_write_cmd = -1;
846 s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT | KBD_MODE_KCC;
847 s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
848 q = &s->queue;
849 q->rptr = 0;
850 q->wptr = 0;
851 q->count = 0;
852 }
854 static void kbd_save(QEMUFile* f, void* opaque)
855 {
856 KBDState *s = (KBDState*)opaque;
858 qemu_put_8s(f, &s->write_cmd);
859 qemu_put_8s(f, &s->status);
860 qemu_put_8s(f, &s->mode);
861 qemu_put_be32s(f, &s->kbd_write_cmd);
862 qemu_put_be32s(f, &s->scan_enabled);
863 qemu_put_be32s(f, &s->mouse_write_cmd);
864 qemu_put_8s(f, &s->mouse_status);
865 qemu_put_8s(f, &s->mouse_resolution);
866 qemu_put_8s(f, &s->mouse_sample_rate);
867 qemu_put_8s(f, &s->mouse_wrap);
868 qemu_put_8s(f, &s->mouse_type);
869 qemu_put_8s(f, &s->mouse_detect_state);
870 qemu_put_be32s(f, &s->mouse_dx);
871 qemu_put_be32s(f, &s->mouse_dy);
872 qemu_put_be32s(f, &s->mouse_dz);
873 qemu_put_8s(f, &s->mouse_buttons);
874 qemu_put_be32s(f, &s->touchpad.absolute);
875 qemu_put_be32s(f, &s->touchpad.high);
876 }
878 static int kbd_load(QEMUFile* f, void* opaque, int version_id)
879 {
880 KBDState *s = (KBDState*)opaque;
882 if (version_id != 2)
883 return -EINVAL;
884 qemu_get_8s(f, &s->write_cmd);
885 qemu_get_8s(f, &s->status);
886 qemu_get_8s(f, &s->mode);
887 qemu_get_be32s(f, &s->kbd_write_cmd);
888 qemu_get_be32s(f, &s->scan_enabled);
889 qemu_get_be32s(f, &s->mouse_write_cmd);
890 qemu_get_8s(f, &s->mouse_status);
891 qemu_get_8s(f, &s->mouse_resolution);
892 qemu_get_8s(f, &s->mouse_sample_rate);
893 qemu_get_8s(f, &s->mouse_wrap);
894 qemu_get_8s(f, &s->mouse_type);
895 qemu_get_8s(f, &s->mouse_detect_state);
896 qemu_get_be32s(f, &s->mouse_dx);
897 qemu_get_be32s(f, &s->mouse_dy);
898 qemu_get_be32s(f, &s->mouse_dz);
899 qemu_get_8s(f, &s->mouse_buttons);
900 qemu_get_be32s(f, &s->touchpad.absolute);
901 qemu_get_be32s(f, &s->touchpad.high);
902 return 0;
903 }
905 void kbd_init(void)
906 {
907 KBDState *s = &kbd_state;
909 kbd_reset(s);
910 register_savevm("pckbd", 0, 2, kbd_save, kbd_load, s);
911 register_ioport_read(0x60, 1, 1, kbd_read_data, s);
912 register_ioport_write(0x60, 1, 1, kbd_write_data, s);
913 register_ioport_read(0x64, 1, 1, kbd_read_status, s);
914 register_ioport_write(0x64, 1, 1, kbd_write_command, s);
916 qemu_add_kbd_event_handler(pc_kbd_put_keycode, s);
917 qemu_add_mouse_event_handler(pc_kbd_mouse_event, s);
918 qemu_register_reset(kbd_reset, s);
919 }