Page 1 of 1

UEFI Simple Pointer Protocol

Posted: Mon Apr 24, 2017 4:38 pm
by ronsor
I am trying to use the UEFI Simple Pointer Protocol but I always get the "EFI_NOT_READY" error:

Code: Select all

	EFI_SIMPLE_POINTER_PROTOCOL* spp;
	EFI_SIMPLE_POINTER_STATE ps;
void InitMouse() {
	EFI_GUID sppg = EFI_SIMPLE_POINTER_PROTOCOL_GUID;
        EFI_HANDLE* handle_buffer;
	UINTN handle_count = 0;
        EFI_STATUS statusx = BS->LocateHandleBuffer( ByProtocol,
                                      &sppg,
                                      NULL,
                                      &handle_count,
                                      &handle_buffer );
	if ( EFI_ERROR(statusx) ) panic("UEFI broken");
        EFI_STATUS status = BS->HandleProtocol( handle_buffer[0],
                                  &sppg,
                                  (VOID **)&spp );
	if (EFI_ERROR(status)) {
		panic("Mouse required!");
	}
	EFI_STATUS xx = spp->Reset(spp, FALSE);
	if ( EFI_ERROR(xx) ) {
		panic("Failed to initialize pointy I/O");
	}
	
}
void UpdateMouse() {
	WaitForSingleEvent(spp->WaitForInput, 0);
	EFI_STATUS x = spp->GetState(spp, &ps);
	printf("%d, %d, %d\n", ps.RelativeMovementX, ps.RelativeMovementY, ps.RelativeMovementZ);
	if ( x == EFI_NOT_READY ) printf("Not ready");
	if ( x == EFI_DEVICE_ERROR ) panic("Error");
}
/*
 void panic(char *msg) -- Print error and halt
 int printf(char *format, ...) -- Standard printf implementation
*/

Re: UEFI Simple Pointer Protocol

Posted: Tue Apr 25, 2017 9:04 am
by zaval
What's WaitForSingleEvent()? I can't find it among UEFI BS. Anyway, you should check its return value. You had to use WaitForEvent() service, checking its retrun value. You omit this and that could be a problem.
Next, the spec says this:
If the state of the pointer device has not changed since the last call to GetState(), then EFI_NOT_READY is returned.
So maybe you didn't move it move it. lol. Probably you check not what you think it is. Your init and "update" sequence looks incomplete. Are you sure you have connected to the mouse handle? How many handles are returned by LocateHandleProtocol()? You just take first.

Re: UEFI Simple Pointer Protocol

Posted: Tue Apr 25, 2017 11:41 am
by ronsor
zaval wrote:What's WaitForSingleEvent()? I can't find it among UEFI BS. Anyway, you should check its return value. You had to use WaitForEvent() service, checking its retrun value. You omit this and that could be a problem.
Next, the spec says this:
If the state of the pointer device has not changed since the last call to GetState(), then EFI_NOT_READY is returned.
So maybe you didn't move it move it. lol. Probably you check not what you think it is. Your init and "update" sequence looks incomplete. Are you sure you have connected to the mouse handle? How many handles are returned by LocateHandleProtocol()? You just take first.
Only one handle is returned (I checked); honestly I have no examples for this so I'm not even sure if I'm missing something. And I did move the mouse.

Re: UEFI Simple Pointer Protocol

Posted: Tue Apr 25, 2017 1:02 pm
by zaval
What about WaitForEvent() function? Does it return EFI_SUCCESS?

Re: UEFI Simple Pointer Protocol

Posted: Tue Apr 25, 2017 1:13 pm
by ronsor
zaval wrote:What about WaitForEvent() function? Does it return EFI_SUCCESS?
WaitForSingleEvent with a '0' timeout just calls WaitForEvent; I have tested both functions and neither returns -- ever. It keeps waiting for a mouse event.

Re: UEFI Simple Pointer Protocol

Posted: Tue Apr 25, 2017 2:15 pm
by zaval
Then it seems not working properly.
Check its Mode structure. What it reports. Maybe there are only zeros, meaning basically lack of support.
Also you might take a look at EFI_DEVICE_PATH_PROTOCOL instance installed on the same handle as the EFI_SIMPLE_POINTER_PROTOCOL instance. It should be installed. And should match the type of mouse (PS/2, USB, serial).
Probably mouse handling is broken at your UEFI fw.
Also, you might try to ConnectController(), in your init routine, on the handle, returned by LocateDevicePath() with the device path obtained from your handle. Probably the driver installed the protocol, but actually never was connected (its Supported/Start routines never were called and thus initialization didn't occur).
Follow this example (version 2.4, page 181)

Code: Select all

EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
EFI_HANDLE Handle;

do {
//
// Find the handle that best matches the Device Path. If it is only a
// partial match the remaining part of the device path is returned in
// RemainingDevicePath.
//
RemainingDevicePath = DevicePath;
Status = gBS->LocateDevicePath (
&gEfiDevicePathProtocolGuid,
&RemainingDevicePath,
&Handle
);
if (EFI_ERROR(Status)) {
return EFI_NOT_FOUND;
}
//
// Connect all drivers that apply to Handle and RemainingDevicePath
// If no drivers are connected Handle, then return EFI_NOT_FOUND
// The Recursive flag is FALSE so only one level will be expanded.
//
Status = gBS->ConnectController (
Handle,
NULL,
RemainingDevicePath,
FALSE
);
if (EFI_ERROR(Status)) {
return EFI_NOT_FOUND;
}
// Loop until RemainingDevicePath is an empty device path
//
} while (!IsDevicePathEnd (RemainingDevicePath));
//
// A handle with DevicePath exists in the handle database
//
return EFI_SUCCESS;

Re: UEFI Simple Pointer Protocol

Posted: Tue Apr 25, 2017 3:57 pm
by ronsor
The mode structure reports "65535" for maximum resolution for X, Y, Z and for the left/right buttons "1"

Re: UEFI Simple Pointer Protocol

Posted: Tue Apr 25, 2017 4:23 pm
by zaval
Well, I only can repeat the suggestion to go through ConnectController() burden, see above. Because probably, somehow, the appropriate driver for mouse was loaded and it installed the needed protocol on the handle, but never have been connected to the controller. Try to connect it in your init function, as described in the example. Read carefully the second example in the ConnectController() desciption. It's page 181 in the 2.4 version of the spec.

Re: UEFI Simple Pointer Protocol

Posted: Wed Apr 26, 2017 4:05 pm
by ronsor
I have concluded QEMU OVMF TIANOCORE UEFI firmware does not support the simple pointer protocol.