]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c
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
)) {
40 Status
= In8042Data (& Data
);
41 if ( EFI_ERROR ( Status
)) {
46 return EFI_DEVICE_ERROR
;
51 Status
= Out8042Command ( READ_CMD_BYTE
);
52 if ( EFI_ERROR ( Status
)) {
56 Status
= In8042Data (& Data
);
57 if ( EFI_ERROR ( Status
)) {
61 Status
= Out8042Command ( WRITE_CMD_BYTE
);
62 if ( EFI_ERROR ( Status
)) {
67 Status
= Out8042Data ( Data
);
68 if ( EFI_ERROR ( Status
)) {
76 Issue command to enable keyboard AUX functionality.
78 @return Status of command issuing.
86 // Send 8042 enable mouse command
88 return Out8042Command ( ENABLE_AUX
);
92 Issue command to disable keyboard AUX functionality.
94 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
96 @return Status of command issuing.
104 // Send 8042 disable mouse command
106 return Out8042Command ( DISABLE_AUX
);
110 Issue command to enable keyboard.
112 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
114 @return Status of command issuing.
122 // Send 8042 enable keyboard command
124 return Out8042Command ( ENABLE_KB
);
128 Issue command to disable keyboard.
130 @return Status of command issuing.
138 // Send 8042 disable keyboard command
140 return Out8042Command ( DISABLE_KB
);
144 Issue command to check keyboard status.
146 @param KeyboardEnable return whether keyboard is enable.
148 @return Status of command issuing.
152 OUT BOOLEAN
* KeyboardEnable
159 // Send command to read KBC command byte
161 Status
= Out8042Command ( READ_CMD_BYTE
);
162 if ( EFI_ERROR ( Status
)) {
166 Status
= In8042Data (& Data
);
167 if ( EFI_ERROR ( Status
)) {
171 // Check keyboard enable or not
173 if (( Data
& CMD_KB_STS
) == CMD_KB_DIS
) {
174 * KeyboardEnable
= FALSE
;
176 * KeyboardEnable
= TRUE
;
183 Issue command to reset keyboard.
185 @return Status of command issuing.
195 Status
= Out8042AuxCommand ( RESET_CMD
, FALSE
);
196 if ( EFI_ERROR ( Status
)) {
200 Status
= In8042AuxData (& Data
);
201 if ( EFI_ERROR ( Status
)) {
205 // Check BAT Complete Code
207 if ( Data
!= PS2MOUSE_BAT1
) {
208 return EFI_DEVICE_ERROR
;
211 Status
= In8042AuxData (& Data
);
212 if ( EFI_ERROR ( Status
)) {
216 // Check BAT Complete Code
218 if ( Data
!= PS2MOUSE_BAT2
) {
219 return EFI_DEVICE_ERROR
;
226 Issue command to set mouse's sample rate
228 @param SampleRate value of sample rate
230 @return Status of command issuing.
233 PS2MouseSetSampleRate (
234 IN MOUSE_SR SampleRate
240 // Send auxiliary command to set mouse sample rate
242 Status
= Out8042AuxCommand ( SETSR_CMD
, FALSE
);
243 if ( EFI_ERROR ( Status
)) {
247 Status
= Out8042AuxData ( SampleRateTbl
[ SampleRate
]);
253 Issue command to set mouse's resolution.
255 @param Resolution value of resolution
257 @return Status of command issuing.
260 PS2MouseSetResolution (
261 IN MOUSE_RE Resolution
267 // Send auxiliary command to set mouse resolution
269 Status
= Out8042AuxCommand ( SETRE_CMD
, FALSE
);
270 if ( EFI_ERROR ( Status
)) {
274 Status
= Out8042AuxData ( ResolutionTbl
[ Resolution
]);
280 Issue command to set mouse's scaling.
282 @param Scaling value of scaling
284 @return Status of command issuing.
292 // Send auxiliary command to set mouse scaling data
294 return Out8042AuxCommand ( Scaling
== Scaling1
? SETSF1_CMD
: SETSF2_CMD
, FALSE
);
298 Issue command to enable Ps2 mouse.
300 @return Status of command issuing.
308 // Send auxiliary command to enable mouse
310 return Out8042AuxCommand ( ENABLE_CMD
, FALSE
);
314 Get mouse packet . Only care first 3 bytes
316 @param MouseDev Pointer of PS2 Mouse Private Data Structure
318 @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet
319 @retval EFI_SUCCESS The data packet is gotten successfully.
324 PS2_MOUSE_DEV
* MouseDev
329 BOOLEAN KeyboardEnable
;
330 UINT8 Packet
[ PS2_PACKET_LENGTH
];
334 INT16 RelativeMovementX
;
335 INT16 RelativeMovementY
;
339 KeyboardEnable
= FALSE
;
340 State
= PS2_READ_BYTE_ONE
;
343 // State machine to get mouse packet
348 case PS2_READ_BYTE_ONE
:
350 // Read mouse first byte data, if failed, immediately return
354 Status
= PS2MouseRead (& Data
, & Count
, State
);
355 if ( EFI_ERROR ( Status
)) {
357 return EFI_NOT_READY
;
362 return EFI_NOT_READY
;
365 if ( IS_PS2_SYNC_BYTE ( Data
)) {
367 State
= PS2_READ_DATA_BYTE
;
369 CheckKbStatus (& KeyboardEnable
);
375 case PS2_READ_DATA_BYTE
:
377 Status
= PS2MouseRead (( Packet
+ 1 ), & Count
, State
);
378 if ( EFI_ERROR ( Status
)) {
379 if ( KeyboardEnable
) {
383 return EFI_NOT_READY
;
387 if ( KeyboardEnable
) {
391 return EFI_NOT_READY
;
394 State
= PS2_PROCESS_PACKET
;
397 case PS2_PROCESS_PACKET
:
398 if ( KeyboardEnable
) {
404 RelativeMovementX
= Packet
[ 1 ];
405 RelativeMovementY
= Packet
[ 2 ];
407 // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0
408 // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn
409 // Byte 1 | 8 bit X Movement
410 // Byte 2 | 8 bit Y Movement
412 // 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.
413 // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement.
416 // First, Clear X and Y high 8 bits
418 RelativeMovementX
= ( INT16
) ( RelativeMovementX
& 0xFF );
419 RelativeMovementY
= ( INT16
) ( RelativeMovementY
& 0xFF );
421 // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff
423 if (( Packet
[ 0 ] & 0x10 ) != 0 ) {
424 RelativeMovementX
= ( INT16
) ( RelativeMovementX
| 0xFF00 );
426 if (( Packet
[ 0 ] & 0x20 ) != 0 ) {
427 RelativeMovementY
= ( INT16
) ( RelativeMovementY
| 0xFF00 );
431 RButton
= ( UINT8
) ( Packet
[ 0 ] & 0x2 );
432 LButton
= ( UINT8
) ( Packet
[ 0 ] & 0x1 );
435 // Update mouse state
437 MouseDev
-> State
. RelativeMovementX
+= RelativeMovementX
;
438 MouseDev
-> State
. RelativeMovementY
-= RelativeMovementY
;
439 MouseDev
-> State
. RightButton
= ( UINT8
) ( RButton
? TRUE
: FALSE
);
440 MouseDev
-> State
. LeftButton
= ( UINT8
) ( LButton
? TRUE
: FALSE
);
441 MouseDev
-> StateChanged
= TRUE
;
449 Read data via IsaIo protocol with given number.
451 @param Buffer Buffer receive data of mouse
452 @param BufSize The size of buffer
453 @param State Check input or read data
455 @return status of reading mouse data.
460 IN OUT UINTN
* BufSize
,
467 Status
= EFI_SUCCESS
;
469 if ( State
== PS2_READ_BYTE_ONE
) {
471 // Check input for mouse
473 Status
= CheckForInput ();
475 if ( EFI_ERROR ( Status
)) {
480 for ( BytesRead
= 0 ; BytesRead
< * BufSize
; BytesRead
++) {
482 Status
= WaitOutputFull ( TIMEOUT
);
483 if ( EFI_ERROR ( Status
)) {
486 Buffer
[ BytesRead
] = IoRead8 ( KBC_DATA_PORT
);
489 // Verify the correct number of bytes read
491 if ( BytesRead
== 0 || BytesRead
!= * BufSize
) {
492 Status
= EFI_NOT_FOUND
;
495 * BufSize
= BytesRead
;
503 I/O work flow of outing 8042 command.
505 @param Command I/O command.
507 @retval EFI_SUCCESS Success to execute I/O work flow
508 @retval EFI_TIMEOUT Keyboard controller time out.
518 // Wait keyboard controller input buffer empty
520 Status
= WaitInputEmpty ( TIMEOUT
);
521 if ( EFI_ERROR ( Status
)) {
527 IoWrite8 ( KBC_CMD_STS_PORT
, Command
);
529 Status
= WaitInputEmpty ( TIMEOUT
);
530 if ( EFI_ERROR ( Status
)) {
538 I/O work flow of outing 8042 data.
540 @param Data Data value
542 @retval EFI_SUCCESS Success to execute I/O work flow
543 @retval EFI_TIMEOUT Keyboard controller time out.
552 // Wait keyboard controller input buffer empty
554 Status
= WaitInputEmpty ( TIMEOUT
);
555 if ( EFI_ERROR ( Status
)) {
559 IoWrite8 ( KBC_DATA_PORT
, Data
);
560 return WaitInputEmpty ( TIMEOUT
);
564 I/O work flow of in 8042 data.
566 @param Data Data value
568 @retval EFI_SUCCESS Success to execute I/O work flow
569 @retval EFI_TIMEOUT Keyboard controller time out.
578 Delay
= TIMEOUT
/ 50 ;
582 // Check keyboard controller status bit 0(output buffer status)
584 if (( IoRead8 ( KBC_CMD_STS_PORT
) & KBC_OUTB
) == KBC_OUTB
) {
590 } while ( Delay
!= 0 );
596 * Data
= IoRead8 ( KBC_DATA_PORT
);
602 I/O work flow of outing 8042 Aux command.
604 @param Command Aux I/O command
605 @param Resend Whether need resend the Aux command.
607 @retval EFI_SUCCESS Success to execute I/O work flow
608 @retval EFI_TIMEOUT Keyboard controller time out.
620 // Wait keyboard controller input buffer empty
622 Status
= WaitInputEmpty ( TIMEOUT
);
623 if ( EFI_ERROR ( Status
)) {
627 // Send write to auxiliary device command
629 IoWrite8 ( KBC_CMD_STS_PORT
, WRITE_AUX_DEV
);
631 Status
= WaitInputEmpty ( TIMEOUT
);
632 if ( EFI_ERROR ( Status
)) {
636 // Send auxiliary device command
638 IoWrite8 ( KBC_DATA_PORT
, Command
);
643 Status
= In8042AuxData (& Data
);
644 if ( EFI_ERROR ( Status
)) {
648 if ( Data
== PS2_ACK
) {
650 // Receive mouse acknowledge, command send success
658 return EFI_DEVICE_ERROR
;
660 } else if ( Data
== PS2_RESEND
) {
664 Status
= Out8042AuxCommand ( Command
, TRUE
);
665 if ( EFI_ERROR ( Status
)) {
671 // Invalid return code
673 return EFI_DEVICE_ERROR
;
681 I/O work flow of outing 8042 Aux data.
683 @param Data Buffer holding return value
685 @retval EFI_SUCCESS Success to execute I/O work flow.
686 @retval EFI_TIMEOUT Keyboard controller time out.
695 // Wait keyboard controller input buffer empty
697 Status
= WaitInputEmpty ( TIMEOUT
);
698 if ( EFI_ERROR ( Status
)) {
702 // Send write to auxiliary device command
704 IoWrite8 ( KBC_CMD_STS_PORT
, WRITE_AUX_DEV
);
706 Status
= WaitInputEmpty ( TIMEOUT
);
707 if ( EFI_ERROR ( Status
)) {
711 IoWrite8 ( KBC_DATA_PORT
, Data
);
713 Status
= WaitInputEmpty ( TIMEOUT
);
714 if ( EFI_ERROR ( Status
)) {
722 I/O work flow of in 8042 Aux data.
724 @param Data Buffer holding return value.
726 @retval EFI_SUCCESS Success to execute I/O work flow
727 @retval EFI_TIMEOUT Keyboard controller time out.
737 // wait for output data
739 Status
= WaitOutputFull ( BAT_TIMEOUT
);
740 if ( EFI_ERROR ( Status
)) {
744 * Data
= IoRead8 ( KBC_DATA_PORT
);
751 Check keyboard controller status, if it is output buffer full and for auxiliary device.
753 @retval EFI_SUCCESS Keyboard controller is ready
754 @retval EFI_NOT_READY Keyboard controller is not ready
763 Data
= IoRead8 ( KBC_CMD_STS_PORT
);
766 // Check keyboard controller status, if it is output buffer full and for auxiliary device
768 if (( Data
& ( KBC_OUTB
| KBC_AUXB
)) != ( KBC_OUTB
| KBC_AUXB
)) {
769 return EFI_NOT_READY
;
776 I/O work flow to wait input buffer empty in given time.
778 @param Timeout Wating time.
780 @retval EFI_TIMEOUT if input is still not empty in given time.
781 @retval EFI_SUCCESS input is empty.
791 Delay
= Timeout
/ 50 ;
794 Data
= IoRead8 ( KBC_CMD_STS_PORT
);
797 // Check keyboard controller status bit 1(input buffer status)
799 if (( Data
& KBC_INPB
) == 0 ) {
805 } while ( Delay
!= 0 );
815 I/O work flow to wait output buffer full in given time.
817 @param Timeout given time
819 @retval EFI_TIMEOUT output is not full in given time
820 @retval EFI_SUCCESS output is full in given time.
830 Delay
= Timeout
/ 50 ;
833 Data
= IoRead8 ( KBC_CMD_STS_PORT
);
836 // Check keyboard controller status bit 0(output buffer status)
837 // & bit5(output buffer for auxiliary device)
839 if (( Data
& ( KBC_OUTB
| KBC_AUXB
)) == ( KBC_OUTB
| KBC_AUXB
)) {
845 } while ( Delay
!= 0 );