mirror of
https://github.com/arehnman/yttrium-virtio-gpu.git
synced 2026-11-07 02:06:32 +00:00
330 lines
7.4 KiB
C++
330 lines
7.4 KiB
C++
#include "device.h"
|
|
#include "assert.h"
|
|
|
|
CDevice::CDevice()
|
|
{
|
|
m_hDevice = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
CDevice::~CDevice()
|
|
{
|
|
if (m_hDevice != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(m_hDevice);
|
|
m_hDevice = INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
|
|
BOOL CDevice::Init(BOOL ovrl)
|
|
{
|
|
PWCHAR DevicePath = NULL;
|
|
if ((DevicePath = GetDevicePath((LPGUID)&GUID_VIOSERIAL_PORT)) != NULL)
|
|
{
|
|
m_hDevice = CreateFile(DevicePath,
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
ovrl ? FILE_FLAG_OVERLAPPED : FILE_ATTRIBUTE_NORMAL,
|
|
NULL );
|
|
|
|
if (m_hDevice != INVALID_HANDLE_VALUE)
|
|
{
|
|
printf("Open vioserial device %S.\n", DevicePath);
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
printf("Cannot find vioserial device.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CDevice::Write(PVOID buf, size_t *size)
|
|
{
|
|
BOOL res = FALSE;
|
|
ULONG ret = 0;
|
|
DWORD bytes = *size;
|
|
|
|
if (!buf) return FALSE;
|
|
|
|
res = WriteFile ( m_hDevice,
|
|
buf,
|
|
bytes,
|
|
&ret,
|
|
NULL
|
|
);
|
|
if (!res)
|
|
{
|
|
printf("Cannot write vioserial device.\n");
|
|
}
|
|
else if ( ret != bytes)
|
|
{
|
|
printf("Write vioserial device error. written = 0x%x, expected = 0x%x\n", ret, bytes);
|
|
*size = ret;
|
|
ret = FALSE;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
BOOL CDevice::WriteEx(PVOID buf, size_t *size)
|
|
{
|
|
BOOL res = FALSE;
|
|
ULONG ret = 0;
|
|
DWORD bytes = *size;
|
|
OVERLAPPED ol = {0};
|
|
|
|
assert( buf );
|
|
|
|
ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
assert( ol.hEvent );
|
|
|
|
res = WriteFile ( m_hDevice,
|
|
buf,
|
|
bytes,
|
|
&ret,
|
|
&ol
|
|
);
|
|
if (!res)
|
|
{
|
|
if (GetLastError() != ERROR_IO_PENDING)
|
|
{
|
|
printf("Write failed but isn't delayed.\n");
|
|
res = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (!GetOverlappedResult(m_hDevice, &ol, &ret, TRUE))
|
|
{
|
|
res = FALSE;
|
|
}
|
|
else
|
|
{
|
|
*size = ret;
|
|
res = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*size = ret;
|
|
res = TRUE;
|
|
}
|
|
|
|
CloseHandle( ol.hEvent );
|
|
return res;
|
|
}
|
|
|
|
BOOL CDevice::Read(PVOID buf, size_t *size)
|
|
{
|
|
BOOL res = FALSE;
|
|
DWORD ret;
|
|
DWORD bytes = *size;
|
|
|
|
if (!buf) return FALSE;
|
|
|
|
memset(buf, '\0', bytes);
|
|
|
|
res = ReadFile ( m_hDevice,
|
|
buf,
|
|
bytes,
|
|
&ret,
|
|
NULL
|
|
);
|
|
if (!res)
|
|
{
|
|
|
|
printf ("PerformReadTest: ReadFile failed: "
|
|
"Error %d\n", GetLastError());
|
|
}
|
|
else if ( ret != bytes)
|
|
{
|
|
printf("Read vioserial device error. get = 0x%x, expected = 0x%x\n", ret, bytes);
|
|
*size = ret;
|
|
ret = FALSE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
BOOL CDevice::ReadEx(PVOID buf, size_t *size)
|
|
{
|
|
BOOL res = FALSE;
|
|
DWORD ret;
|
|
DWORD bytes = *size;
|
|
OVERLAPPED ol = {0};
|
|
|
|
assert(buf);
|
|
|
|
memset(buf, '\0', bytes);
|
|
|
|
ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
assert(ol.hEvent);
|
|
|
|
res = ReadFile ( m_hDevice,
|
|
buf,
|
|
bytes,
|
|
&ret,
|
|
&ol
|
|
);
|
|
if (!res)
|
|
{
|
|
if (GetLastError() != ERROR_IO_PENDING)
|
|
{
|
|
printf("Write failed but isn't delayed.\n");
|
|
res = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (!GetOverlappedResult(m_hDevice, &ol, &ret, TRUE))
|
|
{
|
|
res = FALSE;
|
|
}
|
|
else
|
|
{
|
|
*size = ret;
|
|
res = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*size = ret;
|
|
res = TRUE;
|
|
}
|
|
|
|
CloseHandle( ol.hEvent );
|
|
return res;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!res)
|
|
{
|
|
|
|
printf ("PerformReadTest: ReadFile failed: "
|
|
"Error %d\n", GetLastError());
|
|
}
|
|
else if ( ret != bytes)
|
|
{
|
|
printf("Read vioserial device error. get = 0x%x, expected = 0x%x\n", ret, bytes);
|
|
*size = ret;
|
|
ret = FALSE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
BOOL CDevice::GetInfo(PVOID buf, size_t *size)
|
|
{
|
|
BOOL res = FALSE;
|
|
DWORD ulOutLength = *size;
|
|
ULONG ulReturnedLength = 0;
|
|
PVOID pBuffer = NULL;
|
|
|
|
printf ("%s, buf = %p, size = %d\n", __FUNCTION__, buf, *size);
|
|
res = DeviceIoControl(
|
|
m_hDevice,
|
|
IOCTL_GET_INFORMATION,
|
|
NULL,
|
|
0,
|
|
buf,
|
|
ulOutLength,
|
|
&ulReturnedLength,
|
|
NULL
|
|
);
|
|
|
|
if ( !res )
|
|
{
|
|
printf("Ioctl failed with code %d\n", GetLastError() );
|
|
}
|
|
*size = ulReturnedLength;
|
|
return res;
|
|
}
|
|
|
|
PTCHAR CDevice::GetDevicePath( IN LPGUID InterfaceGuid )
|
|
{
|
|
HDEVINFO HardwareDeviceInfo;
|
|
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
|
|
PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
|
|
ULONG Length, RequiredLength = 0;
|
|
BOOL bResult;
|
|
|
|
HardwareDeviceInfo = SetupDiGetClassDevs(
|
|
InterfaceGuid,
|
|
NULL,
|
|
NULL,
|
|
(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)
|
|
);
|
|
|
|
if (HardwareDeviceInfo == INVALID_HANDLE_VALUE)
|
|
{
|
|
printf("Cannot get class devices.\n");
|
|
return NULL;
|
|
}
|
|
|
|
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
|
|
|
bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo,
|
|
0,
|
|
InterfaceGuid,
|
|
0,
|
|
&DeviceInterfaceData
|
|
);
|
|
|
|
if (bResult == FALSE) {
|
|
printf("Cannot get enumerate device interfaces.\n");
|
|
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
|
|
return NULL;
|
|
}
|
|
|
|
SetupDiGetDeviceInterfaceDetail(
|
|
HardwareDeviceInfo,
|
|
&DeviceInterfaceData,
|
|
NULL,
|
|
0,
|
|
&RequiredLength,
|
|
NULL
|
|
);
|
|
|
|
DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalAlloc(LMEM_FIXED, RequiredLength);
|
|
|
|
if (DeviceInterfaceDetailData == NULL)
|
|
{
|
|
printf("Cannot allocate memory.\n");
|
|
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
|
|
return NULL;
|
|
}
|
|
|
|
DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
|
|
|
Length = RequiredLength;
|
|
|
|
bResult = SetupDiGetDeviceInterfaceDetail(
|
|
HardwareDeviceInfo,
|
|
&DeviceInterfaceData,
|
|
DeviceInterfaceDetailData,
|
|
Length,
|
|
&RequiredLength,
|
|
NULL
|
|
);
|
|
|
|
if (bResult == FALSE)
|
|
{
|
|
printf("Cannot get device interface details.\n");
|
|
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
|
|
LocalFree(DeviceInterfaceDetailData);
|
|
return NULL;
|
|
}
|
|
|
|
return DeviceInterfaceDetailData->DevicePath;
|
|
}
|