diff --git a/idd/LGIdd/CIVSHMEM.cpp b/idd/LGIdd/CIVSHMEM.cpp new file mode 100644 index 00000000..64daf9af --- /dev/null +++ b/idd/LGIdd/CIVSHMEM.cpp @@ -0,0 +1,168 @@ +#include "CIVSHMEM.h" + +#include +#include +#include +#include + +#include "ivshmem/ivshmem.h" + +CIVSHMEM::CIVSHMEM() +{ +} + +CIVSHMEM::~CIVSHMEM() +{ + if (m_handle == INVALID_HANDLE_VALUE) + return; + + Close(); + CloseHandle(m_handle); +} + +bool CIVSHMEM::Init() +{ + HDEVINFO devInfoSet; + SP_DEVINFO_DATA devInfoData; + SP_DEVICE_INTERFACE_DATA devInterfaceData; + PSP_DEVICE_INTERFACE_DETAIL_DATA infData = nullptr; + + devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_IVSHMEM, nullptr, nullptr, + DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + + devInfoData.cbSize = sizeof(devInfoData); + devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + m_devices.clear(); + for (int i = 0; SetupDiEnumDeviceInfo(devInfoSet, i, &devInfoData); ++i) + { + DWORD bus, addr; + if (!SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_BUSNUMBER, + nullptr, (BYTE*)&bus, sizeof(bus), nullptr)) + bus = 0xffff; + + if (!SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_ADDRESS, + nullptr, (BYTE*)&addr, sizeof(addr), nullptr)) + addr = 0xffff; + + IVSHMEMData data; + data.busAddr = ((DWORD64)bus) << 32 | addr; + memcpy(&data.devInfoData, &devInfoData, sizeof(devInfoData)); + m_devices.push_back(data); + } + + if (GetLastError() != ERROR_NO_MORE_ITEMS) + { + m_devices.clear(); + SetupDiDestroyDeviceInfoList(devInfoSet); + return false; + } + + std::sort(m_devices.begin(), m_devices.end(), + [](const IVSHMEMData & a, const IVSHMEMData & b) -> bool + { return a.busAddr < b.busAddr; }); + + + HKEY hkeyLG; + IVSHMEMData * device = nullptr; + DWORD shmDevice = 0; + + if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Looking Glass", &hkeyLG) == ERROR_SUCCESS) + { + DWORD dataType; + DWORD dataSize = sizeof(shmDevice); + if (RegQueryValueExA(hkeyLG, "shmDevice", nullptr, &dataType, (BYTE*)&shmDevice, &dataSize) != ERROR_SUCCESS || + dataType != REG_DWORD) + shmDevice = 0; + } + + DWORD i = 0; + for (auto it = m_devices.begin(); it != m_devices.end(); ++it, ++i) + { + DWORD bus = it->busAddr >> 32; + DWORD addr = it->busAddr & 0xFFFFFFFF; + printf("IVSHMEM %u%c on bus 0x%lx, device 0x%lx, function 0x%lx\n", + i, i == shmDevice ? '*' : ' ', bus, addr >> 16, addr & 0xFFFF); + + if (i == shmDevice) + device = &(*it); + } + + if (!device) + { + SetupDiDestroyDeviceInfoList(devInfoSet); + return false; + } + + if (SetupDiEnumDeviceInterfaces(devInfoSet, &devInfoData, &GUID_DEVINTERFACE_IVSHMEM, 0, &devInterfaceData) == FALSE) + { + SetupDiDestroyDeviceInfoList(devInfoSet); + return false; + } + + DWORD reqSize = 0; + SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterfaceData, nullptr, 0, &reqSize, nullptr); + if (!reqSize) + { + SetupDiDestroyDeviceInfoList(devInfoSet); + return false; + } + + infData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)calloc(1, reqSize); + infData->cbSize = sizeof(PSP_DEVICE_INTERFACE_DETAIL_DATA); + if (!SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterfaceData, infData, reqSize, nullptr, nullptr)) + { + SetupDiDestroyDeviceInfoList(devInfoSet); + return false; + } + + m_handle = CreateFile(infData->DevicePath, 0, 0, nullptr, OPEN_EXISTING, 0, 0); + if (m_handle == INVALID_HANDLE_VALUE) + { + SetupDiDestroyDeviceInfoList(devInfoSet); + return false; + } + + SetupDiDestroyDeviceInfoList(devInfoSet); + return true; +} + +bool CIVSHMEM::Open() +{ + IVSHMEM_SIZE size; + if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_SIZE, nullptr, 0, &size, sizeof(size), nullptr, nullptr)) + { + printf("Failed to request ivshmem size\n"); + return false; + } + + IVSHMEM_MMAP_CONFIG config = {}; + IVSHMEM_MMAP map = {}; + + config.cacheMode = IVSHMEM_CACHE_WRITECOMBINED; + if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_MMAP, &config, sizeof(config), &map, sizeof(map), nullptr, nullptr)) + { + printf("Failed to request ivshmem mmap\n"); + return false; + } + + m_size = (size_t)size; + m_mem = map.ptr; + + return true; +} + +void CIVSHMEM::Close() +{ + if (m_mem == nullptr) + return; + + if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_RELEASE_MMAP, nullptr, 0, nullptr, 0, nullptr, nullptr)) + { + printf("Failed to release ivshmem mmap\n"); + return; + } + + m_size = 0; + m_mem = nullptr; +} \ No newline at end of file diff --git a/idd/LGIdd/CIVSHMEM.h b/idd/LGIdd/CIVSHMEM.h new file mode 100644 index 00000000..2c2d93fa --- /dev/null +++ b/idd/LGIdd/CIVSHMEM.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include + +class CIVSHMEM +{ +private: + struct IVSHMEMData + { + SP_DEVINFO_DATA devInfoData; + DWORD64 busAddr; + }; + + std::vector m_devices; + HANDLE m_handle = INVALID_HANDLE_VALUE; + size_t m_size; + void * m_mem = nullptr; + +public: + CIVSHMEM(); + ~CIVSHMEM(); + + bool Init(); + bool Open(); + void Close(); +}; + diff --git a/idd/LGIdd/CIndirectDeviceContext.cpp b/idd/LGIdd/CIndirectDeviceContext.cpp index 1cb816b3..dbfdf8ac 100644 --- a/idd/LGIdd/CIndirectDeviceContext.cpp +++ b/idd/LGIdd/CIndirectDeviceContext.cpp @@ -3,6 +3,9 @@ void CIndirectDeviceContext::InitAdapter() { + if (!m_ivshmem.Init() || !m_ivshmem.Open()) + return; + IDDCX_ADAPTER_CAPS caps = {}; caps.Size = sizeof(caps); diff --git a/idd/LGIdd/CIndirectDeviceContext.h b/idd/LGIdd/CIndirectDeviceContext.h index a74ac2bf..2a090424 100644 --- a/idd/LGIdd/CIndirectDeviceContext.h +++ b/idd/LGIdd/CIndirectDeviceContext.h @@ -3,12 +3,14 @@ #include #include #include +#include "CIVSHMEM.h" class CIndirectDeviceContext { private: WDFDEVICE m_wdfDevice; IDDCX_ADAPTER m_adapter = nullptr; + CIVSHMEM m_ivshmem; public: CIndirectDeviceContext(_In_ WDFDEVICE wdfDevice) : diff --git a/idd/LGIdd/LGIdd.vcxproj b/idd/LGIdd/LGIdd.vcxproj index 79996588..fdd744ef 100644 --- a/idd/LGIdd/LGIdd.vcxproj +++ b/idd/LGIdd/LGIdd.vcxproj @@ -40,6 +40,7 @@ + @@ -47,6 +48,7 @@ + @@ -217,8 +219,8 @@ true true trace.h - /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions) - $(ProjectDir)..\..\repos\LGMP\lgmp\include;%(AdditionalIncludeDirectories) + /EHsc /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions) + $(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;%(AdditionalIncludeDirectories) %(AdditionalDependencies);OneCoreUAP.lib;avrt.lib @@ -229,8 +231,8 @@ true true trace.h - /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions) - $(ProjectDir)..\..\repos\LGMP\lgmp\include;%(AdditionalIncludeDirectories) + /EHsc /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions) + $(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;%(AdditionalIncludeDirectories) %(AdditionalDependencies);OneCoreUAP.lib;avrt.lib @@ -241,8 +243,8 @@ true true trace.h - /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions) - $(ProjectDir)..\..\repos\LGMP\lgmp\include;%(AdditionalIncludeDirectories) + /EHsc /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions) + $(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;%(AdditionalIncludeDirectories) %(AdditionalDependencies);OneCoreUAP.lib;avrt.lib @@ -253,8 +255,8 @@ true true trace.h - /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions) - $(ProjectDir)..\..\repos\LGMP\lgmp\include;%(AdditionalIncludeDirectories) + /EHsc /D_ATL_NO_WIN_SUPPORT /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /IDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions) + $(ProjectDir)..\..\repos\LGMP\lgmp\include;$(ProjectDir)..\..\vendor;%(AdditionalIncludeDirectories) %(AdditionalDependencies);OneCoreUAP.lib;avrt.lib diff --git a/idd/LGIdd/LGIdd.vcxproj.filters b/idd/LGIdd/LGIdd.vcxproj.filters index e1163cf9..e1a0e075 100644 --- a/idd/LGIdd/LGIdd.vcxproj.filters +++ b/idd/LGIdd/LGIdd.vcxproj.filters @@ -51,6 +51,9 @@ Header Files + + Header Files + @@ -71,5 +74,8 @@ Source Files + + Source Files + \ No newline at end of file