/* debug PC keyboard *///#defineDEBUG_KBD/* debug PC keyboard : only mouse *///#defineDEBUG_MOUSE/* Keyboard Commands */#defineKBD_CMD_SET_LEDS0xED/* Set keyboard leds */#defineKBD_CMD_ECHO0xEE#defineKBD_CMD_GET_ID0xF2/* get keyboard ID */#defineKBD_CMD_SET_RATE0xF3/* Set typematic rate */#defineKBD_CMD_ENABLE0xF4/* Enable scanning */#defineKBD_CMD_RESET_DISABLE0xF5/* reset and disable scanning */#defineKBD_CMD_RESET_ENABLE0xF6/* reset and enable scanning */#defineKBD_CMD_RESET0xFF/* Reset *//* Keyboard Replies */#defineKBD_REPLY_POR0xAA/* Power on reset */#defineKBD_REPLY_ACK0xFA/* Command ACK */#defineKBD_REPLY_RESEND0xFE/* Command NACK, send the cmd again *//* Mouse Commands */#defineAUX_SET_SCALE110xE6/* Set 1:1 scaling */#defineAUX_SET_SCALE210xE7/* Set 2:1 scaling */#defineAUX_SET_RES0xE8/* Set resolution */#defineAUX_GET_SCALE0xE9/* Get scaling factor */#defineAUX_SET_STREAM0xEA/* Set stream mode */#defineAUX_POLL0xEB/* Poll */#defineAUX_RESET_WRAP0xEC/* Reset wrap mode */#defineAUX_SET_WRAP0xEE/* Set wrap mode */#defineAUX_SET_REMOTE0xF0/* Set remote mode */#defineAUX_GET_TYPE0xF2/* Get type */#defineAUX_SET_SAMPLE0xF3/* Set sample rate */#defineAUX_ENABLE_DEV0xF4/* Enable aux device */#defineAUX_DISABLE_DEV0xF5/* Disable aux device */#defineAUX_SET_DEFAULT0xF6#defineAUX_RESET0xFF/* Reset aux device */#defineAUX_ACK0xFA/* Command byte ACK. */#defineMOUSE_STATUS_REMOTE0x40#defineMOUSE_STATUS_ENABLED0x20#defineMOUSE_STATUS_SCALE210x10#definePS2_QUEUE_SIZE256typedefstruct{uint8_tdata[PS2_QUEUE_SIZE];intrptr,wptr,count;}PS2Queue;typedefstruct{PS2Queuequeue;int32_twrite_cmd;void(*update_irq)(void*,int);void*update_arg;}PS2State;typedefstruct{PS2Statecommon;intscan_enabled;
/* Table to convert from PC scancodes to raw scancodes. */staticconstunsignedcharps2_raw_keycode[128]={0,118,22,30,38,37,46,54,61,62,70,69,78,85,102,13,21,29,36,45,44,53,60,67,68,77,84,91,90,20,28,27,35,43,52,51,59,66,75,76,82,14,18,93,26,34,33,42,50,49,58,65,73,74,89,124,17,41,88,5,6,4,12,3,11,2,10,1,9,119,126,108,117,125,123,107,115,116,121,105,114,122,112,113,127,96,97,120,7,15,23,31,39,47,55,63,71,79,86,94,8,16,24,32,40,48,56,64,72,80,87,111,19,25,57,81,83,92,95,98,99,100,101,103,104,106,109,110};
q=&s->queue;if(q->count==0){/*NOTE:ifnodataleft,wereturnthelastkeyboardone(neededforEMM386)*//* XXX: need a timer to do things correctly */index=q->rptr-1;if(index<0)index=PS2_QUEUE_SIZE-1;val=q->data[index];}else{val=q->data[q->rptr];if(++q->rptr==PS2_QUEUE_SIZE)q->rptr=0;q->count--;/* reading deasserts IRQ */s->update_irq(s->update_arg,0);/* reassert IRQs if data left */s->update_irq(s->update_arg,q->count!=0);}returnval;}staticvoidps2_reset_keyboard(PS2KbdState*s){s->scan_enabled=1;}voidps2_write_keyboard(void*opaque,intval){PS2KbdState*s=(PS2KbdState*)opaque;switch(s->common.write_cmd){default:case-1:switch(val){case0x00:ps2_queue(&s->common,KBD_REPLY_ACK);break;case0x05:ps2_queue(&s->common,KBD_REPLY_RESEND);break;caseKBD_CMD_GET_ID:ps2_queue(&s->common,KBD_REPLY_ACK);ps2_queue(&s->common,0xab);ps2_queue(&s->common,0x83);break;caseKBD_CMD_ECHO:ps2_queue(&s->common,KBD_CMD_ECHO);break;caseKBD_CMD_ENABLE:s->scan_enabled=1;ps2_queue(&s->common,KBD_REPLY_ACK);break;caseKBD_CMD_SET_LEDS:caseKBD_CMD_SET_RATE:s->common.write_cmd=val;ps2_queue(&s->common,KBD_REPLY_ACK);break;caseKBD_CMD_RESET_DISABLE:ps2_reset_keyboard(s);s->scan_enabled=0;ps2_queue(&s->common,KBD_REPLY_ACK);break;caseKBD_CMD_RESET_ENABLE:ps2_reset_keyboard(s);s->scan_enabled=1;ps2_queue(&s->common,KBD_REPLY_ACK);break;caseKBD_CMD_RESET:ps2_reset_keyboard(s);ps2_queue(&s->common,KBD_REPLY_ACK);ps2_queue(&s->common,KBD_REPLY_POR);break;default:ps2_queue(&s->common,KBD_REPLY_ACK);break;}break;caseKBD_CMD_SET_LEDS:ps2_queue(&s->common,KBD_REPLY_ACK);s->common.write_cmd=-1;break;caseKBD_CMD_SET_RATE:ps2_queue(&s->common,KBD_REPLY_ACK);s->common.write_cmd=-1;break;}}
staticvoidps2_mouse_send_packet(PS2MouseState*s){unsignedintb;intdx1,dy1,dz1;dx1=s->mouse_dx;dy1=s->mouse_dy;dz1=s->mouse_dz;/* XXX: increase range to 8 bits ? */if(dx1>127)dx1=127;elseif(dx1<-127)dx1=-127;if(dy1>127)dy1=127;elseif(dy1<-127)dy1=-127;b=0x08|((dx1<0)<<4)|((dy1<0)<<5)|(s->mouse_buttons&0x07);ps2_queue(&s->common,b);ps2_queue(&s->common,dx1&0xff);ps2_queue(&s->common,dy1&0xff);/* extra byte for IMPS/2 or IMEX */switch(s->mouse_type){default:break;case3:if(dz1>127)dz1=127;elseif(dz1<-127)dz1=-127;ps2_queue(&s->common,dz1&0xff);break;case4:if(dz1>7)dz1=7;elseif(dz1<-7)dz1=-7;b=(dz1&0x0f)|((s->mouse_buttons&0x18)<<1);ps2_queue(&s->common,b);break;}/* update deltas */s->mouse_dx-=dx1;s->mouse_dy-=dy1;s->mouse_dz-=dz1;}
intdx,intdy,intdz,intbuttons_state){PS2MouseState*s=opaque;/* check if deltas are recorded when disabled */if(!(s->mouse_status&MOUSE_STATUS_ENABLED))return;s->mouse_dx+=dx;s->mouse_dy-=dy;s->mouse_dz+=dz;/* XXX: SDL sometimes generates nul events: we delete them */if(s->mouse_dx==0&&s->mouse_dy==0&&s->mouse_dz==0&&s->mouse_buttons==buttons_state)return;s->mouse_buttons=buttons_state;