/** Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system. @param This - Pointer of simple pointer Protocol. @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. @retval EFI_SUCCESS - The command byte is written successfully. @retval EFI_DEVICE_ERROR - Errors occurred during reseting keyboard. **/ EFI_STATUS EFIAPI MouseAbsolutePointerReset ( IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, IN BOOLEAN ExtendedVerification ) { EFI_STATUS Status; PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev; EFI_TPL OldTpl; BOOLEAN KeyboardEnable; UINT8 Data; MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (This); // // Report reset progress code // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET, MouseAbsolutePointerDev->DevicePath ); KeyboardEnable = FALSE; // // Raise TPL to avoid keyboard operation impact // OldTpl = gBS->RaiseTPL (TPL_NOTIFY); ZeroMem (&MouseAbsolutePointerDev->State, sizeof (EFI_ABSOLUTE_POINTER_STATE)); MouseAbsolutePointerDev->StateChanged = FALSE; // // Exhaust input data // Status = EFI_SUCCESS; while (!EFI_ERROR (Status)) { Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data); } CheckKbStatus (MouseAbsolutePointerDev->IsaIo, &KeyboardEnable); KbcDisableKb (MouseAbsolutePointerDev->IsaIo); MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data); // // if there's data block on KBC data port, read it out // if ((Data & KBC_OUTB) == KBC_OUTB) { MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Data); } Status = EFI_SUCCESS; // // The PS2 mouse driver reset behavior is always successfully return no matter wheater or not there is mouse connected to system. // This behavior is needed by performance speed. The following mouse command only succeessfully finish when mouse device is // connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling // if (ExtendedVerification && CheckMouseAbsolutePointerConnect (MouseAbsolutePointerDev)) { // // Send mouse reset command and set mouse default configure // Status = PS2MouseReset (MouseAbsolutePointerDev->IsaIo); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Exit; } Status = PS2MouseSetSampleRate (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->SampleRate); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Exit; } Status = PS2MouseSetResolution (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Resolution); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Exit; } Status = PS2MouseSetScaling (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Scaling); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Exit; } Status = PS2MouseEnable (MouseAbsolutePointerDev->IsaIo); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Exit; } } Exit: gBS->RestoreTPL (OldTpl); if (KeyboardEnable) { KbcEnableKb (MouseAbsolutePointerDev->IsaIo); } return Status; }
/** Get mouse packet . Only care first 3 bytes @param MouseDev Pointer of PS2 Mouse Private Data Structure @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet @retval EFI_SUCCESS The data packet is gotten successfully. **/ EFI_STATUS PS2MouseGetPacket ( PS2_MOUSE_DEV *MouseDev ) { EFI_STATUS Status; BOOLEAN KeyboardEnable; UINT8 Packet[PS2_PACKET_LENGTH]; UINT8 Data; UINTN Count; UINTN State; INT16 RelativeMovementX; INT16 RelativeMovementY; BOOLEAN LButton; BOOLEAN RButton; KeyboardEnable = FALSE; Count = 1; State = PS2_READ_BYTE_ONE; // // State machine to get mouse packet // while (1) { switch (State) { case PS2_READ_BYTE_ONE: // // Read mouse first byte data, if failed, immediately return // KbcDisableAux (); Status = PS2MouseRead (&Data, &Count, State); if (EFI_ERROR (Status)) { KbcEnableAux (); return EFI_NOT_READY; } if (Count != 1) { KbcEnableAux (); return EFI_NOT_READY; } if (IS_PS2_SYNC_BYTE (Data)) { Packet[0] = Data; State = PS2_READ_DATA_BYTE; CheckKbStatus (&KeyboardEnable); KbcDisableKb (); KbcEnableAux (); } break; case PS2_READ_DATA_BYTE: Count = 2; Status = PS2MouseRead ((Packet + 1), &Count, State); if (EFI_ERROR (Status)) { if (KeyboardEnable) { KbcEnableKb (); } return EFI_NOT_READY; } if (Count != 2) { if (KeyboardEnable) { KbcEnableKb (); } return EFI_NOT_READY; } State = PS2_PROCESS_PACKET; break; case PS2_PROCESS_PACKET: if (KeyboardEnable) { KbcEnableKb (); } // // Decode the packet // RelativeMovementX = Packet[1]; RelativeMovementY = Packet[2]; // // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn // Byte 1 | 8 bit X Movement // Byte 2 | 8 bit Y Movement // // X sign bit + 8 bit X Movement : 9-bit signed twos complement integer that presents the relative displacement of the device in the X direction since the last data transmission. // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement. // // // First, Clear X and Y high 8 bits // RelativeMovementX = (INT16) (RelativeMovementX & 0xFF); RelativeMovementY = (INT16) (RelativeMovementY & 0xFF); // // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff // if ((Packet[0] & 0x10) != 0) { RelativeMovementX = (INT16) (RelativeMovementX | 0xFF00); } if ((Packet[0] & 0x20) != 0) { RelativeMovementY = (INT16) (RelativeMovementY | 0xFF00); } RButton = (UINT8) (Packet[0] & 0x2); LButton = (UINT8) (Packet[0] & 0x1); // // Update mouse state // MouseDev->State.RelativeMovementX += RelativeMovementX; MouseDev->State.RelativeMovementY -= RelativeMovementY; MouseDev->State.RightButton = (UINT8) (RButton ? TRUE : FALSE); MouseDev->State.LeftButton = (UINT8) (LButton ? TRUE : FALSE); MouseDev->StateChanged = TRUE; return EFI_SUCCESS; } } }