]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c
d31665c25df8aa80d25815caa039ae5f2a63d970
2 PS2 Mouse Communication Interface.
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 UINT8 SampleRateTbl
[ MaxSampleRate
] = { 0xa , 0x14 , 0x28 , 0x3c , 0x50 , 0x64 , 0xc8 };
14 UINT8 ResolutionTbl
[ MaxResolution
] = { 0 , 1 , 2 , 3 };
17 Issue self test command via IsaIo interface.
19 @return EFI_SUCCESS Success to do keyboard self testing.
20 @return others Fail to do keyboard self testing.
31 // Keyboard controller self test
33 Status
= Out8042Command ( SELF_TEST
);
34 if ( EFI_ERROR ( Status
)) {
41 Status
= In8042Data (& Data
);
42 if ( EFI_ERROR ( Status
)) {
47 return EFI_DEVICE_ERROR
;
53 Status
= Out8042Command ( READ_CMD_BYTE
);
54 if ( EFI_ERROR ( Status
)) {
58 Status
= In8042Data (& Data
);
59 if ( EFI_ERROR ( Status
)) {
63 Status
= Out8042Command ( WRITE_CMD_BYTE
);
64 if ( EFI_ERROR ( Status
)) {
69 Status
= Out8042Data ( Data
);
70 if ( EFI_ERROR ( Status
)) {
78 Issue command to enable keyboard AUX functionality.
80 @return Status of command issuing.
88 // Send 8042 enable mouse command
90 return Out8042Command ( ENABLE_AUX
);
94 Issue command to disable keyboard AUX functionality.
96 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
98 @return Status of command issuing.
106 // Send 8042 disable mouse command
108 return Out8042Command ( DISABLE_AUX
);
112 Issue command to enable keyboard.
114 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
116 @return Status of command issuing.
124 // Send 8042 enable keyboard command
126 return Out8042Command ( ENABLE_KB
);
130 Issue command to disable keyboard.
132 @return Status of command issuing.
140 // Send 8042 disable keyboard command
142 return Out8042Command ( DISABLE_KB
);
146 Issue command to check keyboard status.
148 @param KeyboardEnable return whether keyboard is enable.
150 @return Status of command issuing.
154 OUT BOOLEAN
* KeyboardEnable
161 // Send command to read KBC command byte
163 Status
= Out8042Command ( READ_CMD_BYTE
);
164 if ( EFI_ERROR ( Status
)) {
168 Status
= In8042Data (& Data
);
169 if ( EFI_ERROR ( Status
)) {
174 // Check keyboard enable or not
176 if (( Data
& CMD_KB_STS
) == CMD_KB_DIS
) {
177 * KeyboardEnable
= FALSE
;
179 * KeyboardEnable
= TRUE
;
186 Issue command to reset keyboard.
188 @return Status of command issuing.
198 Status
= Out8042AuxCommand ( RESET_CMD
, FALSE
);
199 if ( EFI_ERROR ( Status
)) {
203 Status
= In8042AuxData (& Data
);
204 if ( EFI_ERROR ( Status
)) {
209 // Check BAT Complete Code
211 if ( Data
!= PS2MOUSE_BAT1
) {
212 return EFI_DEVICE_ERROR
;
215 Status
= In8042AuxData (& Data
);
216 if ( EFI_ERROR ( Status
)) {
221 // Check BAT Complete Code
223 if ( Data
!= PS2MOUSE_BAT2
) {
224 return EFI_DEVICE_ERROR
;
231 Issue command to set mouse's sample rate
233 @param SampleRate value of sample rate
235 @return Status of command issuing.
238 PS2MouseSetSampleRate (
239 IN MOUSE_SR SampleRate
245 // Send auxiliary command to set mouse sample rate
247 Status
= Out8042AuxCommand ( SETSR_CMD
, FALSE
);
248 if ( EFI_ERROR ( Status
)) {
252 Status
= Out8042AuxData ( SampleRateTbl
[ SampleRate
]);
258 Issue command to set mouse's resolution.
260 @param Resolution value of resolution
262 @return Status of command issuing.
265 PS2MouseSetResolution (
266 IN MOUSE_RE Resolution
272 // Send auxiliary command to set mouse resolution
274 Status
= Out8042AuxCommand ( SETRE_CMD
, FALSE
);
275 if ( EFI_ERROR ( Status
)) {
279 Status
= Out8042AuxData ( ResolutionTbl
[ Resolution
]);
285 Issue command to set mouse's scaling.
287 @param Scaling value of scaling
289 @return Status of command issuing.
297 // Send auxiliary command to set mouse scaling data
299 return Out8042AuxCommand ( Scaling
== Scaling1
? SETSF1_CMD
: SETSF2_CMD
, FALSE
);
303 Issue command to enable Ps2 mouse.
305 @return Status of command issuing.
313 // Send auxiliary command to enable mouse
315 return Out8042AuxCommand ( ENABLE_CMD
, FALSE
);
319 Get mouse packet . Only care first 3 bytes
321 @param MouseDev Pointer of PS2 Mouse Private Data Structure
323 @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet
324 @retval EFI_SUCCESS The data packet is gotten successfully.
329 PS2_MOUSE_DEV
* MouseDev
334 BOOLEAN KeyboardEnable
;
335 UINT8 Packet
[ PS2_PACKET_LENGTH
];
339 INT16 RelativeMovementX
;
340 INT16 RelativeMovementY
;
344 KeyboardEnable
= FALSE
;
345 State
= PS2_READ_BYTE_ONE
;
348 // State machine to get mouse packet
352 case PS2_READ_BYTE_ONE
:
354 // Read mouse first byte data, if failed, immediately return
358 Status
= PS2MouseRead (& Data
, & Count
, State
);
359 if ( EFI_ERROR ( Status
)) {
361 return EFI_NOT_READY
;
366 return EFI_NOT_READY
;
369 if ( IS_PS2_SYNC_BYTE ( Data
)) {
371 State
= PS2_READ_DATA_BYTE
;
373 CheckKbStatus (& KeyboardEnable
);
380 case PS2_READ_DATA_BYTE
:
382 Status
= PS2MouseRead (( Packet
+ 1 ), & Count
, State
);
383 if ( EFI_ERROR ( Status
)) {
384 if ( KeyboardEnable
) {
388 return EFI_NOT_READY
;
392 if ( KeyboardEnable
) {
396 return EFI_NOT_READY
;
399 State
= PS2_PROCESS_PACKET
;
402 case PS2_PROCESS_PACKET
:
403 if ( KeyboardEnable
) {
410 RelativeMovementX
= Packet
[ 1 ];
411 RelativeMovementY
= Packet
[ 2 ];
413 // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0
414 // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn
415 // Byte 1 | 8 bit X Movement
416 // Byte 2 | 8 bit Y Movement
418 // 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.
419 // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement.
422 // First, Clear X and Y high 8 bits
424 RelativeMovementX
= ( INT16
)( RelativeMovementX
& 0xFF );
425 RelativeMovementY
= ( INT16
)( RelativeMovementY
& 0xFF );
427 // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff
429 if (( Packet
[ 0 ] & 0x10 ) != 0 ) {
430 RelativeMovementX
= ( INT16
)( RelativeMovementX
| 0xFF00 );
433 if (( Packet
[ 0 ] & 0x20 ) != 0 ) {
434 RelativeMovementY
= ( INT16
)( RelativeMovementY
| 0xFF00 );
437 RButton
= ( UINT8
)( Packet
[ 0 ] & 0x2 );
438 LButton
= ( UINT8
)( Packet
[ 0 ] & 0x1 );
441 // Update mouse state
443 MouseDev
-> State
. RelativeMovementX
+= RelativeMovementX
;
444 MouseDev
-> State
. RelativeMovementY
-= RelativeMovementY
;
445 MouseDev
-> State
. RightButton
= ( UINT8
)( RButton
? TRUE
: FALSE
);
446 MouseDev
-> State
. LeftButton
= ( UINT8
)( LButton
? TRUE
: FALSE
);
447 MouseDev
-> StateChanged
= TRUE
;
455 Read data via IsaIo protocol with given number.
457 @param Buffer Buffer receive data of mouse
458 @param BufSize The size of buffer
459 @param State Check input or read data
461 @return status of reading mouse data.
466 IN OUT UINTN
* BufSize
,
473 Status
= EFI_SUCCESS
;
475 if ( State
== PS2_READ_BYTE_ONE
) {
477 // Check input for mouse
479 Status
= CheckForInput ();
481 if ( EFI_ERROR ( Status
)) {
486 for ( BytesRead
= 0 ; BytesRead
< * BufSize
; BytesRead
++) {
487 Status
= WaitOutputFull ( TIMEOUT
);
488 if ( EFI_ERROR ( Status
)) {
492 Buffer
[ BytesRead
] = IoRead8 ( KBC_DATA_PORT
);
496 // Verify the correct number of bytes read
498 if (( BytesRead
== 0 ) || ( BytesRead
!= * BufSize
)) {
499 Status
= EFI_NOT_FOUND
;
502 * BufSize
= BytesRead
;
511 I/O work flow of outing 8042 command.
513 @param Command I/O command.
515 @retval EFI_SUCCESS Success to execute I/O work flow
516 @retval EFI_TIMEOUT Keyboard controller time out.
526 // Wait keyboard controller input buffer empty
528 Status
= WaitInputEmpty ( TIMEOUT
);
529 if ( EFI_ERROR ( Status
)) {
536 IoWrite8 ( KBC_CMD_STS_PORT
, Command
);
538 Status
= WaitInputEmpty ( TIMEOUT
);
539 if ( EFI_ERROR ( Status
)) {
547 I/O work flow of outing 8042 data.
549 @param Data Data value
551 @retval EFI_SUCCESS Success to execute I/O work flow
552 @retval EFI_TIMEOUT Keyboard controller time out.
562 // Wait keyboard controller input buffer empty
564 Status
= WaitInputEmpty ( TIMEOUT
);
565 if ( EFI_ERROR ( Status
)) {
569 IoWrite8 ( KBC_DATA_PORT
, Data
);
570 return WaitInputEmpty ( TIMEOUT
);
574 I/O work flow of in 8042 data.
576 @param Data Data value
578 @retval EFI_SUCCESS Success to execute I/O work flow
579 @retval EFI_TIMEOUT Keyboard controller time out.
588 Delay
= TIMEOUT
/ 50 ;
592 // Check keyboard controller status bit 0(output buffer status)
594 if (( IoRead8 ( KBC_CMD_STS_PORT
) & KBC_OUTB
) == KBC_OUTB
) {
600 } while ( Delay
!= 0 );
606 * Data
= IoRead8 ( KBC_DATA_PORT
);
612 I/O work flow of outing 8042 Aux command.
614 @param Command Aux I/O command
615 @param Resend Whether need resend the Aux command.
617 @retval EFI_SUCCESS Success to execute I/O work flow
618 @retval EFI_TIMEOUT Keyboard controller time out.
630 // Wait keyboard controller input buffer empty
632 Status
= WaitInputEmpty ( TIMEOUT
);
633 if ( EFI_ERROR ( Status
)) {
638 // Send write to auxiliary device command
640 IoWrite8 ( KBC_CMD_STS_PORT
, WRITE_AUX_DEV
);
642 Status
= WaitInputEmpty ( TIMEOUT
);
643 if ( EFI_ERROR ( Status
)) {
648 // Send auxiliary device command
650 IoWrite8 ( KBC_DATA_PORT
, Command
);
655 Status
= In8042AuxData (& Data
);
656 if ( EFI_ERROR ( Status
)) {
660 if ( Data
== PS2_ACK
) {
662 // Receive mouse acknowledge, command send success
669 return EFI_DEVICE_ERROR
;
670 } else if ( Data
== PS2_RESEND
) {
674 Status
= Out8042AuxCommand ( Command
, TRUE
);
675 if ( EFI_ERROR ( Status
)) {
680 // Invalid return code
682 return EFI_DEVICE_ERROR
;
689 I/O work flow of outing 8042 Aux data.
691 @param Data Buffer holding return value
693 @retval EFI_SUCCESS Success to execute I/O work flow.
694 @retval EFI_TIMEOUT Keyboard controller time out.
704 // Wait keyboard controller input buffer empty
706 Status
= WaitInputEmpty ( TIMEOUT
);
707 if ( EFI_ERROR ( Status
)) {
712 // Send write to auxiliary device command
714 IoWrite8 ( KBC_CMD_STS_PORT
, WRITE_AUX_DEV
);
716 Status
= WaitInputEmpty ( TIMEOUT
);
717 if ( EFI_ERROR ( Status
)) {
721 IoWrite8 ( KBC_DATA_PORT
, Data
);
723 Status
= WaitInputEmpty ( TIMEOUT
);
724 if ( EFI_ERROR ( Status
)) {
732 I/O work flow of in 8042 Aux data.
734 @param Data Buffer holding return value.
736 @retval EFI_SUCCESS Success to execute I/O work flow
737 @retval EFI_TIMEOUT Keyboard controller time out.
747 // wait for output data
749 Status
= WaitOutputFull ( BAT_TIMEOUT
);
750 if ( EFI_ERROR ( Status
)) {
754 * Data
= IoRead8 ( KBC_DATA_PORT
);
760 Check keyboard controller status, if it is output buffer full and for auxiliary device.
762 @retval EFI_SUCCESS Keyboard controller is ready
763 @retval EFI_NOT_READY Keyboard controller is not ready
772 Data
= IoRead8 ( KBC_CMD_STS_PORT
);
775 // Check keyboard controller status, if it is output buffer full and for auxiliary device
777 if (( Data
& ( KBC_OUTB
| KBC_AUXB
)) != ( KBC_OUTB
| KBC_AUXB
)) {
778 return EFI_NOT_READY
;
785 I/O work flow to wait input buffer empty in given time.
787 @param Timeout Waiting time.
789 @retval EFI_TIMEOUT if input is still not empty in given time.
790 @retval EFI_SUCCESS input is empty.
800 Delay
= Timeout
/ 50 ;
803 Data
= IoRead8 ( KBC_CMD_STS_PORT
);
806 // Check keyboard controller status bit 1(input buffer status)
808 if (( Data
& KBC_INPB
) == 0 ) {
814 } while ( Delay
!= 0 );
824 I/O work flow to wait output buffer full in given time.
826 @param Timeout given time
828 @retval EFI_TIMEOUT output is not full in given time
829 @retval EFI_SUCCESS output is full in given time.
839 Delay
= Timeout
/ 50 ;
842 Data
= IoRead8 ( KBC_CMD_STS_PORT
);
845 // Check keyboard controller status bit 0(output buffer status)
846 // & bit5(output buffer for auxiliary device)
848 if (( Data
& ( KBC_OUTB
| KBC_AUXB
)) == ( KBC_OUTB
| KBC_AUXB
)) {
854 } while ( Delay
!= 0 );