]>
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 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 UINT8 SampleRateTbl
[ MaxSampleRate
] = { 0xa , 0x14 , 0x28 , 0x3c , 0x50 , 0x64 , 0xc8 };
20 UINT8 ResolutionTbl
[ MaxResolution
] = { 0 , 1 , 2 , 3 };
23 Issue self test command via IsaIo interface.
25 @return EFI_SUCCESS Success to do keyboard self testing.
26 @return others Fail to do keyboard self testing.
37 // Keyboard controller self test
39 Status
= Out8042Command ( SELF_TEST
);
40 if ( EFI_ERROR ( Status
)) {
46 Status
= In8042Data (& Data
);
47 if ( EFI_ERROR ( Status
)) {
52 return EFI_DEVICE_ERROR
;
57 Status
= Out8042Command ( READ_CMD_BYTE
);
58 if ( EFI_ERROR ( Status
)) {
62 Status
= In8042Data (& Data
);
63 if ( EFI_ERROR ( Status
)) {
67 Status
= Out8042Command ( WRITE_CMD_BYTE
);
68 if ( EFI_ERROR ( Status
)) {
73 Status
= Out8042Data ( Data
);
74 if ( EFI_ERROR ( Status
)) {
82 Issue command to enable keyboard AUX functionality.
84 @return Status of command issuing.
92 // Send 8042 enable mouse command
94 return Out8042Command ( ENABLE_AUX
);
98 Issue command to disable keyboard AUX functionality.
100 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
102 @return Status of command issuing.
110 // Send 8042 disable mouse command
112 return Out8042Command ( DISABLE_AUX
);
116 Issue command to enable keyboard.
118 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
120 @return Status of command issuing.
128 // Send 8042 enable keyboard command
130 return Out8042Command ( ENABLE_KB
);
134 Issue command to disable keyboard.
136 @return Status of command issuing.
144 // Send 8042 disable keyboard command
146 return Out8042Command ( DISABLE_KB
);
150 Issue command to check keyboard status.
152 @param KeyboardEnable return whether keyboard is enable.
154 @return Status of command issuing.
158 OUT BOOLEAN
* KeyboardEnable
165 // Send command to read KBC command byte
167 Status
= Out8042Command ( READ_CMD_BYTE
);
168 if ( EFI_ERROR ( Status
)) {
172 Status
= In8042Data (& Data
);
173 if ( EFI_ERROR ( Status
)) {
177 // Check keyboard enable or not
179 if (( Data
& CMD_KB_STS
) == CMD_KB_DIS
) {
180 * KeyboardEnable
= FALSE
;
182 * KeyboardEnable
= TRUE
;
189 Issue command to reset keyboard.
191 @return Status of command issuing.
201 Status
= Out8042AuxCommand ( RESET_CMD
, FALSE
);
202 if ( EFI_ERROR ( Status
)) {
206 Status
= In8042AuxData (& Data
);
207 if ( EFI_ERROR ( Status
)) {
211 // Check BAT Complete Code
213 if ( Data
!= PS2MOUSE_BAT1
) {
214 return EFI_DEVICE_ERROR
;
217 Status
= In8042AuxData (& Data
);
218 if ( EFI_ERROR ( Status
)) {
222 // Check BAT Complete Code
224 if ( Data
!= PS2MOUSE_BAT2
) {
225 return EFI_DEVICE_ERROR
;
232 Issue command to set mouse's sample rate
234 @param SampleRate value of sample rate
236 @return Status of command issuing.
239 PS2MouseSetSampleRate (
240 IN MOUSE_SR SampleRate
246 // Send auxiliary command to set mouse sample rate
248 Status
= Out8042AuxCommand ( SETSR_CMD
, FALSE
);
249 if ( EFI_ERROR ( Status
)) {
253 Status
= Out8042AuxData ( SampleRateTbl
[ SampleRate
]);
259 Issue command to set mouse's resolution.
261 @param Resolution value of resolution
263 @return Status of command issuing.
266 PS2MouseSetResolution (
267 IN MOUSE_RE Resolution
273 // Send auxiliary command to set mouse resolution
275 Status
= Out8042AuxCommand ( SETRE_CMD
, FALSE
);
276 if ( EFI_ERROR ( Status
)) {
280 Status
= Out8042AuxData ( ResolutionTbl
[ Resolution
]);
286 Issue command to set mouse's scaling.
288 @param Scaling value of scaling
290 @return Status of command issuing.
298 // Send auxiliary command to set mouse scaling data
300 return Out8042AuxCommand ( Scaling
== Scaling1
? SETSF1_CMD
: SETSF2_CMD
, FALSE
);
304 Issue command to enable Ps2 mouse.
306 @return Status of command issuing.
314 // Send auxiliary command to enable mouse
316 return Out8042AuxCommand ( ENABLE_CMD
, FALSE
);
320 Get mouse packet . Only care first 3 bytes
322 @param MouseDev Pointer of PS2 Mouse Private Data Structure
324 @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet
325 @retval EFI_SUCCESS The data packet is gotten successfully.
330 PS2_MOUSE_DEV
* MouseDev
335 BOOLEAN KeyboardEnable
;
336 UINT8 Packet
[ PS2_PACKET_LENGTH
];
340 INT16 RelativeMovementX
;
341 INT16 RelativeMovementY
;
345 KeyboardEnable
= FALSE
;
346 State
= PS2_READ_BYTE_ONE
;
349 // State machine to get mouse packet
354 case PS2_READ_BYTE_ONE
:
356 // Read mouse first byte data, if failed, immediately return
360 Status
= PS2MouseRead (& Data
, & Count
, State
);
361 if ( EFI_ERROR ( Status
)) {
363 return EFI_NOT_READY
;
368 return EFI_NOT_READY
;
371 if ( IS_PS2_SYNC_BYTE ( Data
)) {
373 State
= PS2_READ_DATA_BYTE
;
375 CheckKbStatus (& KeyboardEnable
);
381 case PS2_READ_DATA_BYTE
:
383 Status
= PS2MouseRead (( Packet
+ 1 ), & Count
, State
);
384 if ( EFI_ERROR ( Status
)) {
385 if ( KeyboardEnable
) {
389 return EFI_NOT_READY
;
393 if ( KeyboardEnable
) {
397 return EFI_NOT_READY
;
400 State
= PS2_PROCESS_PACKET
;
403 case PS2_PROCESS_PACKET
:
404 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 );
432 if (( Packet
[ 0 ] & 0x20 ) != 0 ) {
433 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
++) {
488 Status
= WaitOutputFull ( TIMEOUT
);
489 if ( EFI_ERROR ( Status
)) {
492 Buffer
[ BytesRead
] = IoRead8 ( KBC_DATA_PORT
);
495 // Verify the correct number of bytes read
497 if ( BytesRead
== 0 || BytesRead
!= * BufSize
) {
498 Status
= EFI_NOT_FOUND
;
501 * BufSize
= BytesRead
;
509 I/O work flow of outing 8042 command.
511 @param Command I/O command.
513 @retval EFI_SUCCESS Success to excute I/O work flow
514 @retval EFI_TIMEOUT Keyboard controller time out.
524 // Wait keyboard controller input buffer empty
526 Status
= WaitInputEmpty ( TIMEOUT
);
527 if ( EFI_ERROR ( Status
)) {
533 IoWrite8 ( KBC_CMD_STS_PORT
, Command
);
535 Status
= WaitInputEmpty ( TIMEOUT
);
536 if ( EFI_ERROR ( Status
)) {
544 I/O work flow of outing 8042 data.
546 @param Data Data value
548 @retval EFI_SUCCESS Success to excute I/O work flow
549 @retval EFI_TIMEOUT Keyboard controller time out.
558 // Wait keyboard controller input buffer empty
560 Status
= WaitInputEmpty ( TIMEOUT
);
561 if ( EFI_ERROR ( Status
)) {
565 IoWrite8 ( KBC_DATA_PORT
, Data
);
566 return WaitInputEmpty ( TIMEOUT
);
570 I/O work flow of in 8042 data.
572 @param Data Data value
574 @retval EFI_SUCCESS Success to excute I/O work flow
575 @retval EFI_TIMEOUT Keyboard controller time out.
584 Delay
= TIMEOUT
/ 50 ;
588 // Check keyboard controller status bit 0(output buffer status)
590 if (( IoRead8 ( KBC_CMD_STS_PORT
) & KBC_OUTB
) == KBC_OUTB
) {
596 } while ( Delay
!= 0 );
602 * Data
= IoRead8 ( KBC_DATA_PORT
);
608 I/O work flow of outing 8042 Aux command.
610 @param Command Aux I/O command
611 @param Resend Whether need resend the Aux command.
613 @retval EFI_SUCCESS Success to excute I/O work flow
614 @retval EFI_TIMEOUT Keyboard controller time out.
626 // Wait keyboard controller input buffer empty
628 Status
= WaitInputEmpty ( TIMEOUT
);
629 if ( EFI_ERROR ( Status
)) {
633 // Send write to auxiliary device command
635 IoWrite8 ( KBC_CMD_STS_PORT
, WRITE_AUX_DEV
);
637 Status
= WaitInputEmpty ( TIMEOUT
);
638 if ( EFI_ERROR ( Status
)) {
642 // Send auxiliary device command
644 IoWrite8 ( KBC_DATA_PORT
, Command
);
649 Status
= In8042AuxData (& Data
);
650 if ( EFI_ERROR ( Status
)) {
654 if ( Data
== PS2_ACK
) {
656 // Receive mouse acknowledge, command send success
664 return EFI_DEVICE_ERROR
;
666 } else if ( Data
== PS2_RESEND
) {
670 Status
= Out8042AuxCommand ( Command
, TRUE
);
671 if ( EFI_ERROR ( Status
)) {
677 // Invalid return code
679 return EFI_DEVICE_ERROR
;
687 I/O work flow of outing 8042 Aux data.
689 @param Data Buffer holding return value
691 @retval EFI_SUCCESS Success to excute I/O work flow.
692 @retval EFI_TIMEOUT Keyboard controller time out.
701 // Wait keyboard controller input buffer empty
703 Status
= WaitInputEmpty ( TIMEOUT
);
704 if ( EFI_ERROR ( Status
)) {
708 // Send write to auxiliary device command
710 IoWrite8 ( KBC_CMD_STS_PORT
, WRITE_AUX_DEV
);
712 Status
= WaitInputEmpty ( TIMEOUT
);
713 if ( EFI_ERROR ( Status
)) {
717 IoWrite8 ( KBC_DATA_PORT
, Data
);
719 Status
= WaitInputEmpty ( TIMEOUT
);
720 if ( EFI_ERROR ( Status
)) {
728 I/O work flow of in 8042 Aux data.
730 @param Data Buffer holding return value.
732 @retval EFI_SUCCESS Success to excute I/O work flow
733 @retval EFI_TIMEOUT Keyboard controller time out.
743 // wait for output data
745 Status
= WaitOutputFull ( BAT_TIMEOUT
);
746 if ( EFI_ERROR ( Status
)) {
750 * Data
= IoRead8 ( KBC_DATA_PORT
);
757 Check keyboard controller status, if it is output buffer full and for auxiliary device.
759 @retval EFI_SUCCESS Keyboard controller is ready
760 @retval EFI_NOT_READY Keyboard controller is not ready
769 Data
= IoRead8 ( KBC_CMD_STS_PORT
);
772 // Check keyboard controller status, if it is output buffer full and for auxiliary device
774 if (( Data
& ( KBC_OUTB
| KBC_AUXB
)) != ( KBC_OUTB
| KBC_AUXB
)) {
775 return EFI_NOT_READY
;
782 I/O work flow to wait input buffer empty in given time.
784 @param Timeout Wating time.
786 @retval EFI_TIMEOUT if input is still not empty in given time.
787 @retval EFI_SUCCESS input is empty.
797 Delay
= Timeout
/ 50 ;
800 Data
= IoRead8 ( KBC_CMD_STS_PORT
);
803 // Check keyboard controller status bit 1(input buffer status)
805 if (( Data
& KBC_INPB
) == 0 ) {
811 } while ( Delay
!= 0 );
821 I/O work flow to wait output buffer full in given time.
823 @param Timeout given time
825 @retval EFI_TIMEOUT output is not full in given time
826 @retval EFI_SUCCESS output is full in given time.
836 Delay
= Timeout
/ 50 ;
839 Data
= IoRead8 ( KBC_CMD_STS_PORT
);
842 // Check keyboard controller status bit 0(output buffer status)
843 // & bit5(output buffer for auxiliary device)
845 if (( Data
& ( KBC_OUTB
| KBC_AUXB
)) == ( KBC_OUTB
| KBC_AUXB
)) {
851 } while ( Delay
!= 0 );