From b5975e0f052cb6aec53d6ef28bc5301b6b8cf106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20G=C3=B6tzinger?= Date: Fri, 10 May 2019 11:48:38 +0200 Subject: [PATCH] [host] [c-host] added support to specify IVSHMEM device [host] basic IVSHMEM device selecting implemented Minor fixes for IVSHMEM device scanning [c-host] added support to specify IVSHMEM device --- c-host/platform/Windows/src/platform.c | 23 +++- host/IVSHMEM.cpp | 144 +++++++++++++++++++++---- host/IVSHMEM.h | 8 +- host/Service.cpp | 4 +- host/Service.h | 6 ++ host/main.cpp | 35 +++++- 6 files changed, 196 insertions(+), 24 deletions(-) diff --git a/c-host/platform/Windows/src/platform.c b/c-host/platform/Windows/src/platform.c index 092d95c9..749b710c 100644 --- a/c-host/platform/Windows/src/platform.c +++ b/c-host/platform/Windows/src/platform.c @@ -27,6 +27,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "interface/platform.h" #include "common/debug.h" +#include "common/option.h" #include "windows/debug.h" #include "ivshmem/Public.h" @@ -112,6 +113,24 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine { int result = 0; + struct Option options[] = + { + { + .module = "os", + .name = "shmDevice", + .description = "The IVSHMEM device to use", + .value = { + .type = OPTION_TYPE_INT, + .v.x_int = 0, + }, + .validator = NULL, + .printHelp = NULL + }, + {0} + }; + + option_register(options); + // convert the command line to the standard argc and argv LPWSTR * wargv = CommandLineToArgvW(GetCommandLineW(), &app.argc); app.argv = malloc(sizeof(char *) * app.argc); @@ -210,6 +229,8 @@ finish: bool app_init() { + int shmDevice = option_get_int("os", "shmDevice"); + HDEVINFO deviceInfoSet; PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; @@ -218,7 +239,7 @@ bool app_init() memset(&deviceInterfaceData, 0, sizeof(SP_DEVICE_INTERFACE_DATA)); deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - if (SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, 0, &deviceInterfaceData) == FALSE) + if (SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, shmDevice, &deviceInterfaceData) == FALSE) { DWORD error = GetLastError(); if (error == ERROR_NO_MORE_ITEMS) diff --git a/host/IVSHMEM.cpp b/host/IVSHMEM.cpp index 10b13aa9..3d615a4e 100644 --- a/host/IVSHMEM.cpp +++ b/host/IVSHMEM.cpp @@ -26,6 +26,77 @@ Place, Suite 330, Boston, MA 02111-1307 USA IVSHMEM * IVSHMEM::m_instance = NULL; +void IVSHMEM::listDevices() { + + HDEVINFO deviceInfoSet; + PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL; + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + + deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE); + ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA)); + deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + fprintf(stderr, "Found devices:\n"); + + DWORD i = 0; + while(SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, i, &deviceInterfaceData) != FALSE) + { + DWORD reqSize = 0; + SP_DEVINFO_DATA d; + d.cbSize = sizeof(SP_DEVINFO_DATA); + + SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &reqSize, &d); + if (!reqSize) + { + fprintf(stderr, "SetupDiGetDeviceInterfaceDetail"); + break; + } + + infData = static_cast(malloc(reqSize)); + ZeroMemory(infData, reqSize); + infData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, infData, reqSize, NULL, NULL)) + { + fprintf(stderr, "SetupDiGetDeviceInterfaceDetail"); + break; + } + + DWORD bus, addr, slot, func; + + if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, &d,SPDRP_BUSNUMBER,NULL,(PBYTE)&bus,sizeof(bus),NULL)) + { + DEBUG_ERROR("SetupDiGetDeviceRegistryProperty - SPDRP_BUSNUMBER: %lu\n", GetLastError()); + free(infData); + break; + } + + if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, &d,SPDRP_ADDRESS,NULL, (PBYTE)&addr,sizeof(addr),NULL)) + { + DEBUG_ERROR("SetupDiGetDeviceRegistryProperty - SPDRP_ADDRESS: %lu\n", GetLastError()); + free(infData); + break; + } + + slot = (addr >> 16) & 0xFFFF; + func = addr & 0xFFFF; + + fprintf(stderr, "[%lu] Found Device: %ls\n" + " Bus: 0x%lx\n" + " Slot: 0x%lx\n" + " Func: 0x%lx\n", + i, infData->DevicePath, bus, slot, func); + i++; + } + + DWORD error = GetLastError(); + if (error != ERROR_NO_MORE_ITEMS) + { + fprintf(stderr, "Unknown error on index %u: %lu\n", i, error); + } + + fprintf(stderr, "%lu devices found\n\n", i); +} + IVSHMEM::IVSHMEM() : m_initialized(false), m_handle(INVALID_HANDLE_VALUE), @@ -41,7 +112,7 @@ IVSHMEM::~IVSHMEM() DeInitialize(); } -bool IVSHMEM::Initialize() +bool IVSHMEM::Initialize(PCI_DEVICE dev) { if (m_initialized) DeInitialize(); @@ -54,23 +125,13 @@ bool IVSHMEM::Initialize() ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA)); deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - while (true) + DWORD devid = 0; + while (SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, devid, &deviceInterfaceData) != FALSE) { - if (SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, 0, &deviceInterfaceData) == FALSE) - { - DWORD error = GetLastError(); - if (error == ERROR_NO_MORE_ITEMS) - { - DEBUG_ERROR("Unable to enumerate the device, is it attached?"); - break; - } - - DEBUG_ERROR("SetupDiEnumDeviceInterfaces failed"); - break; - } - DWORD reqSize = 0; - SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &reqSize, NULL); + SP_DEVINFO_DATA d; + d.cbSize = sizeof(SP_DEVINFO_DATA); + SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &reqSize, &d); if (!reqSize) { DEBUG_ERROR("SetupDiGetDeviceInterfaceDetail"); @@ -83,22 +144,67 @@ bool IVSHMEM::Initialize() if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, infData, reqSize, NULL, NULL)) { DEBUG_ERROR("SetupDiGetDeviceInterfaceDetail"); + free(infData); break; } + DWORD bus, addr, slot, func; + + if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, &d,SPDRP_BUSNUMBER,NULL,(PBYTE)&bus,sizeof(bus),NULL)) + { + DEBUG_ERROR("SetupDiGetDeviceRegistryProperty - SPDRP_BUSNUMBER"); + free(infData); + break; + } + + if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, &d,SPDRP_ADDRESS,NULL, (PBYTE)&addr,sizeof(addr),NULL)) + { + DEBUG_ERROR("SetupDiGetDeviceRegistryProperty - SPDRP_ADDRESS"); + free(infData); + break; + } + + slot = (addr >> 16) & 0xFFFF; + func = addr & 0xFFFF; + + if (dev.bus != bus || dev.addr != slot || dev.func != func) //not the right device, keep searching + { + free(infData); + devid++; + continue; + } + + fprintf(stderr, "Found Device at Index %lu: %ls\n" + " Bus: %lu\n" + " Addr: %lu\n" + " Func: %lu\n", + devid, infData->DevicePath, bus, slot, func); + m_handle = CreateFile(infData->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0); if (m_handle == INVALID_HANDLE_VALUE) { DEBUG_ERROR("CreateFile returned INVALID_HANDLE_VALUE"); + free(infData); break; } m_initialized = true; break; } - - if (infData) - free(infData); + + DWORD error = GetLastError(); + if (m_initialized == false) + { + if (error == ERROR_NO_MORE_ITEMS) + { + DEBUG_ERROR("Unable to enumerate the device, is it attached?"); + } + else + { + DEBUG_ERROR("Unable to enumerate the device. Error: %lu\n", error); + } + + } SetupDiDestroyDeviceInfoList(deviceInfoSet); return m_initialized; diff --git a/host/IVSHMEM.h b/host/IVSHMEM.h index 2e8f19e3..f6932d05 100644 --- a/host/IVSHMEM.h +++ b/host/IVSHMEM.h @@ -23,6 +23,10 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include #include +struct PCI_DEVICE { + BYTE bus, addr, func; +}; + class IVSHMEM { public: @@ -33,7 +37,9 @@ public: return m_instance; } - bool Initialize(); + static void listDevices(); + + bool Initialize(PCI_DEVICE dev); void DeInitialize(); bool IsInitialized(); diff --git a/host/Service.cpp b/host/Service.cpp index 114a3084..96f9a1de 100644 --- a/host/Service.cpp +++ b/host/Service.cpp @@ -27,6 +27,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "Util.h" #include "CaptureFactory.h" +PCI_DEVICE Service::s_dev = {0x13, 0x01, 0x00}; + Service::Service() : m_initialized(false), m_memory(NULL), @@ -40,7 +42,7 @@ Service::Service() : m_consoleSessionID = WTSGetActiveConsoleSessionId(); m_ivshmem = IVSHMEM::Get(); - if (!m_ivshmem->Initialize()) + if (!m_ivshmem->Initialize(s_dev)) throw "IVSHMEM failed to initalize"; if (m_ivshmem->GetSize() < sizeof(KVMFRHeader)) diff --git a/host/Service.h b/host/Service.h index 6014c39d..be19e460 100644 --- a/host/Service.h +++ b/host/Service.h @@ -61,6 +61,11 @@ public: } } + static void SetDevice(PCI_DEVICE dev) + { + s_dev = dev; + } + bool Initialize(ICapture * captureDevice); void DeInitialize(); ProcessStatus Process(); @@ -95,6 +100,7 @@ private: size_t m_frameSize; uint64_t m_dataOffset[MAX_FRAMES]; int m_frameIndex; + static PCI_DEVICE s_dev; static DWORD WINAPI _CursorThread(LPVOID lpParameter) { return Service::Instance().CursorThread(); } DWORD CursorThread(); diff --git a/host/main.cpp b/host/main.cpp index 75472048..3e82c837 100644 --- a/host/main.cpp +++ b/host/main.cpp @@ -196,7 +196,7 @@ int run() int parseArgs(struct StartupArgs & args) { int c; - while((c = getopt(__argc, __argv, "hc:o:fl")) != -1) + while((c = getopt(__argc, __argv, "hc:o:fld:")) != -1) { switch (c) { @@ -253,6 +253,36 @@ int parseArgs(struct StartupArgs & args) case 'l': doLicense(); return -1; + + case 'd': + if (optarg == NULL || strlen(optarg) == 0) + { + setupConsole(); + fprintf(stderr, "Device ID missing\n"); + return -1; + } + else if (*optarg == '?') + { + setupConsole(); + IVSHMEM::listDevices(); + return -1; + } + else + { + PCI_DEVICE dev; + int cnt = sscanf_s(optarg, "%hhu,%hhu,%hhu", &dev.bus, &dev.addr, &dev.func); + if (cnt == 3) + { + Service::SetDevice(dev); + } + else + { + setupConsole(); + fprintf(stderr, "Invalid Parameter\n"); + return -1; + } + } + break; } } @@ -271,7 +301,8 @@ void doHelp() " -c Specify the capture device to use or ? to list availble (device is probed if not specified)\n" " -o Option to pass to the capture device, may be specified multiple times for extra options\n" " -f Foreground mode\n" - " -l License information\n", + " -l License information\n" + " -d Specify the IVSHMEM device with \",,\" or ? to list available\n", app, app );