symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/ps2.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * QEMU PS/2 keyboard/mouse 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 "hw.h"
       
    25 #include "ps2.h"
       
    26 #include "console.h"
       
    27 #include "gui.h"
       
    28 
       
    29 /* debug PC keyboard */
       
    30 //#define DEBUG_KBD
       
    31 
       
    32 /* debug PC keyboard : only mouse */
       
    33 //#define DEBUG_MOUSE
       
    34 
       
    35 /* Keyboard Commands */
       
    36 #define KBD_CMD_SET_LEDS	0xED	/* Set keyboard leds */
       
    37 #define KBD_CMD_ECHO     	0xEE
       
    38 #define KBD_CMD_SCANCODE	0xF0	/* Get/set scancode set */
       
    39 #define KBD_CMD_GET_ID 	        0xF2	/* get keyboard ID */
       
    40 #define KBD_CMD_SET_RATE	0xF3	/* Set typematic rate */
       
    41 #define KBD_CMD_ENABLE		0xF4	/* Enable scanning */
       
    42 #define KBD_CMD_RESET_DISABLE	0xF5	/* reset and disable scanning */
       
    43 #define KBD_CMD_RESET_ENABLE   	0xF6    /* reset and enable scanning */
       
    44 #define KBD_CMD_RESET		0xFF	/* Reset */
       
    45 
       
    46 /* Keyboard Replies */
       
    47 #define KBD_REPLY_POR		0xAA	/* Power on reset */
       
    48 #define KBD_REPLY_ID		0xAB	/* Keyboard ID */
       
    49 #define KBD_REPLY_ACK		0xFA	/* Command ACK */
       
    50 #define KBD_REPLY_RESEND	0xFE	/* Command NACK, send the cmd again */
       
    51 
       
    52 /* Mouse Commands */
       
    53 #define AUX_SET_SCALE11		0xE6	/* Set 1:1 scaling */
       
    54 #define AUX_SET_SCALE21		0xE7	/* Set 2:1 scaling */
       
    55 #define AUX_SET_RES		0xE8	/* Set resolution */
       
    56 #define AUX_GET_SCALE		0xE9	/* Get scaling factor */
       
    57 #define AUX_SET_STREAM		0xEA	/* Set stream mode */
       
    58 #define AUX_POLL		0xEB	/* Poll */
       
    59 #define AUX_RESET_WRAP		0xEC	/* Reset wrap mode */
       
    60 #define AUX_SET_WRAP		0xEE	/* Set wrap mode */
       
    61 #define AUX_SET_REMOTE		0xF0	/* Set remote mode */
       
    62 #define AUX_GET_TYPE		0xF2	/* Get type */
       
    63 #define AUX_SET_SAMPLE		0xF3	/* Set sample rate */
       
    64 #define AUX_ENABLE_DEV		0xF4	/* Enable aux device */
       
    65 #define AUX_DISABLE_DEV		0xF5	/* Disable aux device */
       
    66 #define AUX_SET_DEFAULT		0xF6
       
    67 #define AUX_RESET		0xFF	/* Reset aux device */
       
    68 #define AUX_ACK			0xFA	/* Command byte ACK. */
       
    69 
       
    70 #define MOUSE_STATUS_REMOTE     0x40
       
    71 #define MOUSE_STATUS_ENABLED    0x20
       
    72 #define MOUSE_STATUS_SCALE21    0x10
       
    73 
       
    74 #define PS2_QUEUE_SIZE 256
       
    75 
       
    76 typedef struct {
       
    77     uint8_t data[PS2_QUEUE_SIZE];
       
    78     int rptr, wptr, count;
       
    79 } PS2Queue;
       
    80 
       
    81 typedef struct {
       
    82     PS2Queue queue;
       
    83     int32_t write_cmd;
       
    84     void (*update_irq)(void *, int);
       
    85     void *update_arg;
       
    86 } PS2State;
       
    87 
       
    88 typedef struct {
       
    89     PS2State common;
       
    90     int scan_enabled;
       
    91     /* Qemu uses translated PC scancodes internally.  To avoid multiple
       
    92        conversions we do the translation (if any) in the PS/2 emulation
       
    93        not the keyboard controller.  */
       
    94     int translate;
       
    95     int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
       
    96 } PS2KbdState;
       
    97 
       
    98 typedef struct {
       
    99     PS2State common;
       
   100     uint8_t mouse_status;
       
   101     uint8_t mouse_resolution;
       
   102     uint8_t mouse_sample_rate;
       
   103     uint8_t mouse_wrap;
       
   104     uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
       
   105     uint8_t mouse_detect_state;
       
   106     int mouse_dx; /* current values, needed for 'poll' mode */
       
   107     int mouse_dy;
       
   108     int mouse_dz;
       
   109     uint8_t mouse_buttons;
       
   110 } PS2MouseState;
       
   111 
       
   112 /* Table to convert from PC scancodes to raw scancodes.  */
       
   113 static const unsigned char ps2_raw_keycode[128] = {
       
   114           0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
       
   115          21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
       
   116          35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
       
   117          50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
       
   118          11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
       
   119         114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
       
   120          71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
       
   121          19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
       
   122 };
       
   123 
       
   124 void ps2_queue(void *opaque, int b)
       
   125 {
       
   126     PS2State *s = (PS2State *)opaque;
       
   127     PS2Queue *q = &s->queue;
       
   128 
       
   129     if (q->count >= PS2_QUEUE_SIZE)
       
   130         return;
       
   131     q->data[q->wptr] = b;
       
   132     if (++q->wptr == PS2_QUEUE_SIZE)
       
   133         q->wptr = 0;
       
   134     q->count++;
       
   135     s->update_irq(s->update_arg, 1);
       
   136 }
       
   137 
       
   138 /*
       
   139    keycode is expressed as follow:
       
   140    bit 7    - 0 key pressed, 1 = key released
       
   141    bits 6-0 - translated scancode set 2
       
   142  */
       
   143 static void ps2_put_keycode(void *opaque, int keycode)
       
   144 {
       
   145     PS2KbdState *s = opaque;
       
   146 
       
   147     /* XXX: add support for scancode sets 1 and 3 */
       
   148     if (!s->translate && keycode < 0xe0 && s->scancode_set == 2)
       
   149       {
       
   150         if (keycode & 0x80)
       
   151             ps2_queue(&s->common, 0xf0);
       
   152         keycode = ps2_raw_keycode[keycode & 0x7f];
       
   153       }
       
   154     ps2_queue(&s->common, keycode);
       
   155 }
       
   156 
       
   157 uint32_t ps2_read_data(void *opaque)
       
   158 {
       
   159     PS2State *s = (PS2State *)opaque;
       
   160     PS2Queue *q;
       
   161     int val, index;
       
   162 
       
   163     q = &s->queue;
       
   164     if (q->count == 0) {
       
   165         /* NOTE: if no data left, we return the last keyboard one
       
   166            (needed for EMM386) */
       
   167         /* XXX: need a timer to do things correctly */
       
   168         index = q->rptr - 1;
       
   169         if (index < 0)
       
   170             index = PS2_QUEUE_SIZE - 1;
       
   171         val = q->data[index];
       
   172     } else {
       
   173         val = q->data[q->rptr];
       
   174         if (++q->rptr == PS2_QUEUE_SIZE)
       
   175             q->rptr = 0;
       
   176         q->count--;
       
   177         /* reading deasserts IRQ */
       
   178         s->update_irq(s->update_arg, 0);
       
   179         /* reassert IRQs if data left */
       
   180         s->update_irq(s->update_arg, q->count != 0);
       
   181     }
       
   182     return val;
       
   183 }
       
   184 
       
   185 static void ps2_reset_keyboard(PS2KbdState *s)
       
   186 {
       
   187     s->scan_enabled = 1;
       
   188     s->scancode_set = 2;
       
   189 }
       
   190 
       
   191 void ps2_write_keyboard(void *opaque, int val)
       
   192 {
       
   193     PS2KbdState *s = (PS2KbdState *)opaque;
       
   194 
       
   195     switch(s->common.write_cmd) {
       
   196     default:
       
   197     case -1:
       
   198         switch(val) {
       
   199         case 0x00:
       
   200             ps2_queue(&s->common, KBD_REPLY_ACK);
       
   201             break;
       
   202         case 0x05:
       
   203             ps2_queue(&s->common, KBD_REPLY_RESEND);
       
   204             break;
       
   205         case KBD_CMD_GET_ID:
       
   206             ps2_queue(&s->common, KBD_REPLY_ACK);
       
   207             /* We emulate a MF2 AT keyboard here */
       
   208             ps2_queue(&s->common, KBD_REPLY_ID);
       
   209             if (s->translate)
       
   210                 ps2_queue(&s->common, 0x41);
       
   211             else
       
   212                 ps2_queue(&s->common, 0x83);
       
   213             break;
       
   214         case KBD_CMD_ECHO:
       
   215             ps2_queue(&s->common, KBD_CMD_ECHO);
       
   216             break;
       
   217         case KBD_CMD_ENABLE:
       
   218             s->scan_enabled = 1;
       
   219             ps2_queue(&s->common, KBD_REPLY_ACK);
       
   220             break;
       
   221         case KBD_CMD_SCANCODE:
       
   222         case KBD_CMD_SET_LEDS:
       
   223         case KBD_CMD_SET_RATE:
       
   224             s->common.write_cmd = val;
       
   225             ps2_queue(&s->common, KBD_REPLY_ACK);
       
   226             break;
       
   227         case KBD_CMD_RESET_DISABLE:
       
   228             ps2_reset_keyboard(s);
       
   229             s->scan_enabled = 0;
       
   230             ps2_queue(&s->common, KBD_REPLY_ACK);
       
   231             break;
       
   232         case KBD_CMD_RESET_ENABLE:
       
   233             ps2_reset_keyboard(s);
       
   234             s->scan_enabled = 1;
       
   235             ps2_queue(&s->common, KBD_REPLY_ACK);
       
   236             break;
       
   237         case KBD_CMD_RESET:
       
   238             ps2_reset_keyboard(s);
       
   239             ps2_queue(&s->common, KBD_REPLY_ACK);
       
   240             ps2_queue(&s->common, KBD_REPLY_POR);
       
   241             break;
       
   242         default:
       
   243             ps2_queue(&s->common, KBD_REPLY_ACK);
       
   244             break;
       
   245         }
       
   246         break;
       
   247     case KBD_CMD_SCANCODE:
       
   248         if (val == 0) {
       
   249             if (s->scancode_set == 1)
       
   250                 ps2_put_keycode(s, 0x43);
       
   251             else if (s->scancode_set == 2)
       
   252                 ps2_put_keycode(s, 0x41);
       
   253             else if (s->scancode_set == 3)
       
   254                 ps2_put_keycode(s, 0x3f);
       
   255         } else {
       
   256             if (val >= 1 && val <= 3)
       
   257                 s->scancode_set = val;
       
   258             ps2_queue(&s->common, KBD_REPLY_ACK);
       
   259         }
       
   260         s->common.write_cmd = -1;
       
   261         break;
       
   262     case KBD_CMD_SET_LEDS:
       
   263         ps2_queue(&s->common, KBD_REPLY_ACK);
       
   264         s->common.write_cmd = -1;
       
   265         break;
       
   266     case KBD_CMD_SET_RATE:
       
   267         ps2_queue(&s->common, KBD_REPLY_ACK);
       
   268         s->common.write_cmd = -1;
       
   269         break;
       
   270     }
       
   271 }
       
   272 
       
   273 /* Set the scancode translation mode.
       
   274    0 = raw scancodes.
       
   275    1 = translated scancodes (used by qemu internally).  */
       
   276 
       
   277 void ps2_keyboard_set_translation(void *opaque, int mode)
       
   278 {
       
   279     PS2KbdState *s = (PS2KbdState *)opaque;
       
   280     s->translate = mode;
       
   281 }
       
   282 
       
   283 static void ps2_mouse_send_packet(PS2MouseState *s)
       
   284 {
       
   285     unsigned int b;
       
   286     int dx1, dy1, dz1;
       
   287 
       
   288     dx1 = s->mouse_dx;
       
   289     dy1 = s->mouse_dy;
       
   290     dz1 = s->mouse_dz;
       
   291     /* XXX: increase range to 8 bits ? */
       
   292     if (dx1 > 127)
       
   293         dx1 = 127;
       
   294     else if (dx1 < -127)
       
   295         dx1 = -127;
       
   296     if (dy1 > 127)
       
   297         dy1 = 127;
       
   298     else if (dy1 < -127)
       
   299         dy1 = -127;
       
   300     b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
       
   301     ps2_queue(&s->common, b);
       
   302     ps2_queue(&s->common, dx1 & 0xff);
       
   303     ps2_queue(&s->common, dy1 & 0xff);
       
   304     /* extra byte for IMPS/2 or IMEX */
       
   305     switch(s->mouse_type) {
       
   306     default:
       
   307         break;
       
   308     case 3:
       
   309         if (dz1 > 127)
       
   310             dz1 = 127;
       
   311         else if (dz1 < -127)
       
   312                 dz1 = -127;
       
   313         ps2_queue(&s->common, dz1 & 0xff);
       
   314         break;
       
   315     case 4:
       
   316         if (dz1 > 7)
       
   317             dz1 = 7;
       
   318         else if (dz1 < -7)
       
   319             dz1 = -7;
       
   320         b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
       
   321         ps2_queue(&s->common, b);
       
   322         break;
       
   323     }
       
   324 
       
   325     /* update deltas */
       
   326     s->mouse_dx -= dx1;
       
   327     s->mouse_dy -= dy1;
       
   328     s->mouse_dz -= dz1;
       
   329 }
       
   330 
       
   331 static void ps2_mouse_event(void *opaque,
       
   332                             int dx, int dy, int dz, int buttons_state)
       
   333 {
       
   334     PS2MouseState *s = opaque;
       
   335 
       
   336     /* check if deltas are recorded when disabled */
       
   337     if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
       
   338         return;
       
   339 
       
   340     s->mouse_dx += dx;
       
   341     s->mouse_dy -= dy;
       
   342     s->mouse_dz += dz;
       
   343     /* XXX: SDL sometimes generates nul events: we delete them */
       
   344     if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
       
   345         s->mouse_buttons == buttons_state)
       
   346 	return;
       
   347     s->mouse_buttons = buttons_state;
       
   348 
       
   349     if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
       
   350         (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
       
   351         for(;;) {
       
   352             /* if not remote, send event. Multiple events are sent if
       
   353                too big deltas */
       
   354             ps2_mouse_send_packet(s);
       
   355             if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
       
   356                 break;
       
   357         }
       
   358     }
       
   359 }
       
   360 
       
   361 void ps2_mouse_fake_event(void *opaque)
       
   362 {
       
   363     ps2_mouse_event(opaque, 1, 0, 0, 0);
       
   364 }
       
   365 
       
   366 void ps2_write_mouse(void *opaque, int val)
       
   367 {
       
   368     PS2MouseState *s = (PS2MouseState *)opaque;
       
   369 #ifdef DEBUG_MOUSE
       
   370     printf("kbd: write mouse 0x%02x\n", val);
       
   371 #endif
       
   372     switch(s->common.write_cmd) {
       
   373     default:
       
   374     case -1:
       
   375         /* mouse command */
       
   376         if (s->mouse_wrap) {
       
   377             if (val == AUX_RESET_WRAP) {
       
   378                 s->mouse_wrap = 0;
       
   379                 ps2_queue(&s->common, AUX_ACK);
       
   380                 return;
       
   381             } else if (val != AUX_RESET) {
       
   382                 ps2_queue(&s->common, val);
       
   383                 return;
       
   384             }
       
   385         }
       
   386         switch(val) {
       
   387         case AUX_SET_SCALE11:
       
   388             s->mouse_status &= ~MOUSE_STATUS_SCALE21;
       
   389             ps2_queue(&s->common, AUX_ACK);
       
   390             break;
       
   391         case AUX_SET_SCALE21:
       
   392             s->mouse_status |= MOUSE_STATUS_SCALE21;
       
   393             ps2_queue(&s->common, AUX_ACK);
       
   394             break;
       
   395         case AUX_SET_STREAM:
       
   396             s->mouse_status &= ~MOUSE_STATUS_REMOTE;
       
   397             ps2_queue(&s->common, AUX_ACK);
       
   398             break;
       
   399         case AUX_SET_WRAP:
       
   400             s->mouse_wrap = 1;
       
   401             ps2_queue(&s->common, AUX_ACK);
       
   402             break;
       
   403         case AUX_SET_REMOTE:
       
   404             s->mouse_status |= MOUSE_STATUS_REMOTE;
       
   405             ps2_queue(&s->common, AUX_ACK);
       
   406             break;
       
   407         case AUX_GET_TYPE:
       
   408             ps2_queue(&s->common, AUX_ACK);
       
   409             ps2_queue(&s->common, s->mouse_type);
       
   410             break;
       
   411         case AUX_SET_RES:
       
   412         case AUX_SET_SAMPLE:
       
   413             s->common.write_cmd = val;
       
   414             ps2_queue(&s->common, AUX_ACK);
       
   415             break;
       
   416         case AUX_GET_SCALE:
       
   417             ps2_queue(&s->common, AUX_ACK);
       
   418             ps2_queue(&s->common, s->mouse_status);
       
   419             ps2_queue(&s->common, s->mouse_resolution);
       
   420             ps2_queue(&s->common, s->mouse_sample_rate);
       
   421             break;
       
   422         case AUX_POLL:
       
   423             ps2_queue(&s->common, AUX_ACK);
       
   424             ps2_mouse_send_packet(s);
       
   425             break;
       
   426         case AUX_ENABLE_DEV:
       
   427             s->mouse_status |= MOUSE_STATUS_ENABLED;
       
   428             ps2_queue(&s->common, AUX_ACK);
       
   429             break;
       
   430         case AUX_DISABLE_DEV:
       
   431             s->mouse_status &= ~MOUSE_STATUS_ENABLED;
       
   432             ps2_queue(&s->common, AUX_ACK);
       
   433             break;
       
   434         case AUX_SET_DEFAULT:
       
   435             s->mouse_sample_rate = 100;
       
   436             s->mouse_resolution = 2;
       
   437             s->mouse_status = 0;
       
   438             ps2_queue(&s->common, AUX_ACK);
       
   439             break;
       
   440         case AUX_RESET:
       
   441             s->mouse_sample_rate = 100;
       
   442             s->mouse_resolution = 2;
       
   443             s->mouse_status = 0;
       
   444             s->mouse_type = 0;
       
   445             ps2_queue(&s->common, AUX_ACK);
       
   446             ps2_queue(&s->common, 0xaa);
       
   447             ps2_queue(&s->common, s->mouse_type);
       
   448             break;
       
   449         default:
       
   450             break;
       
   451         }
       
   452         break;
       
   453     case AUX_SET_SAMPLE:
       
   454         s->mouse_sample_rate = val;
       
   455         /* detect IMPS/2 or IMEX */
       
   456         switch(s->mouse_detect_state) {
       
   457         default:
       
   458         case 0:
       
   459             if (val == 200)
       
   460                 s->mouse_detect_state = 1;
       
   461             break;
       
   462         case 1:
       
   463             if (val == 100)
       
   464                 s->mouse_detect_state = 2;
       
   465             else if (val == 200)
       
   466                 s->mouse_detect_state = 3;
       
   467             else
       
   468                 s->mouse_detect_state = 0;
       
   469             break;
       
   470         case 2:
       
   471             if (val == 80)
       
   472                 s->mouse_type = 3; /* IMPS/2 */
       
   473             s->mouse_detect_state = 0;
       
   474             break;
       
   475         case 3:
       
   476             if (val == 80)
       
   477                 s->mouse_type = 4; /* IMEX */
       
   478             s->mouse_detect_state = 0;
       
   479             break;
       
   480         }
       
   481         ps2_queue(&s->common, AUX_ACK);
       
   482         s->common.write_cmd = -1;
       
   483         break;
       
   484     case AUX_SET_RES:
       
   485         s->mouse_resolution = val;
       
   486         ps2_queue(&s->common, AUX_ACK);
       
   487         s->common.write_cmd = -1;
       
   488         break;
       
   489     }
       
   490 }
       
   491 
       
   492 static void ps2_reset(void *opaque)
       
   493 {
       
   494     PS2State *s = (PS2State *)opaque;
       
   495     PS2Queue *q;
       
   496     s->write_cmd = -1;
       
   497     q = &s->queue;
       
   498     q->rptr = 0;
       
   499     q->wptr = 0;
       
   500     q->count = 0;
       
   501 }
       
   502 
       
   503 static void ps2_common_save (QEMUFile *f, PS2State *s)
       
   504 {
       
   505     qemu_put_be32 (f, s->write_cmd);
       
   506     qemu_put_be32 (f, s->queue.rptr);
       
   507     qemu_put_be32 (f, s->queue.wptr);
       
   508     qemu_put_be32 (f, s->queue.count);
       
   509     qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
       
   510 }
       
   511 
       
   512 static void ps2_common_load (QEMUFile *f, PS2State *s)
       
   513 {
       
   514     s->write_cmd=qemu_get_be32 (f);
       
   515     s->queue.rptr=qemu_get_be32 (f);
       
   516     s->queue.wptr=qemu_get_be32 (f);
       
   517     s->queue.count=qemu_get_be32 (f);
       
   518     qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
       
   519 }
       
   520 
       
   521 static void ps2_kbd_save(QEMUFile* f, void* opaque)
       
   522 {
       
   523     PS2KbdState *s = (PS2KbdState*)opaque;
       
   524 
       
   525     ps2_common_save (f, &s->common);
       
   526     qemu_put_be32(f, s->scan_enabled);
       
   527     qemu_put_be32(f, s->translate);
       
   528     qemu_put_be32(f, s->scancode_set);
       
   529 }
       
   530 
       
   531 static void ps2_mouse_save(QEMUFile* f, void* opaque)
       
   532 {
       
   533     PS2MouseState *s = (PS2MouseState*)opaque;
       
   534 
       
   535     ps2_common_save (f, &s->common);
       
   536     qemu_put_8s(f, &s->mouse_status);
       
   537     qemu_put_8s(f, &s->mouse_resolution);
       
   538     qemu_put_8s(f, &s->mouse_sample_rate);
       
   539     qemu_put_8s(f, &s->mouse_wrap);
       
   540     qemu_put_8s(f, &s->mouse_type);
       
   541     qemu_put_8s(f, &s->mouse_detect_state);
       
   542     qemu_put_be32(f, s->mouse_dx);
       
   543     qemu_put_be32(f, s->mouse_dy);
       
   544     qemu_put_be32(f, s->mouse_dz);
       
   545     qemu_put_8s(f, &s->mouse_buttons);
       
   546 }
       
   547 
       
   548 static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
       
   549 {
       
   550     PS2KbdState *s = (PS2KbdState*)opaque;
       
   551 
       
   552     if (version_id != 2 && version_id != 3)
       
   553         return -EINVAL;
       
   554 
       
   555     ps2_common_load (f, &s->common);
       
   556     s->scan_enabled=qemu_get_be32(f);
       
   557     s->translate=qemu_get_be32(f);
       
   558     if (version_id == 3)
       
   559         s->scancode_set=qemu_get_be32(f);
       
   560     else
       
   561         s->scancode_set=2;
       
   562     return 0;
       
   563 }
       
   564 
       
   565 static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
       
   566 {
       
   567     PS2MouseState *s = (PS2MouseState*)opaque;
       
   568 
       
   569     if (version_id != 2)
       
   570         return -EINVAL;
       
   571 
       
   572     ps2_common_load (f, &s->common);
       
   573     qemu_get_8s(f, &s->mouse_status);
       
   574     qemu_get_8s(f, &s->mouse_resolution);
       
   575     qemu_get_8s(f, &s->mouse_sample_rate);
       
   576     qemu_get_8s(f, &s->mouse_wrap);
       
   577     qemu_get_8s(f, &s->mouse_type);
       
   578     qemu_get_8s(f, &s->mouse_detect_state);
       
   579     s->mouse_dx=qemu_get_be32(f);
       
   580     s->mouse_dy=qemu_get_be32(f);
       
   581     s->mouse_dz=qemu_get_be32(f);
       
   582     qemu_get_8s(f, &s->mouse_buttons);
       
   583     return 0;
       
   584 }
       
   585 
       
   586 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
       
   587 {
       
   588     PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
       
   589 
       
   590     s->common.update_irq = update_irq;
       
   591     s->common.update_arg = update_arg;
       
   592     s->scancode_set = 2;
       
   593     ps2_reset(&s->common);
       
   594     register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
       
   595     gui_register_dev_key_callback(ps2_put_keycode, s);
       
   596     qemu_register_reset(ps2_reset, &s->common);
       
   597     return s;
       
   598 }
       
   599 
       
   600 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
       
   601 {
       
   602     PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
       
   603 
       
   604     s->common.update_irq = update_irq;
       
   605     s->common.update_arg = update_arg;
       
   606     ps2_reset(&s->common);
       
   607     register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
       
   608     qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
       
   609     qemu_register_reset(ps2_reset, &s->common);
       
   610     return s;
       
   611 }