[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
This commit is contained in:
Paul Götzinger 2019-05-10 11:48:38 +02:00 committed by Geoffrey McRae
parent 53ade56b4e
commit b5975e0f05
6 changed files with 196 additions and 24 deletions

View File

@ -27,6 +27,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "interface/platform.h" #include "interface/platform.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/option.h"
#include "windows/debug.h" #include "windows/debug.h"
#include "ivshmem/Public.h" #include "ivshmem/Public.h"
@ -112,6 +113,24 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
{ {
int result = 0; 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 // convert the command line to the standard argc and argv
LPWSTR * wargv = CommandLineToArgvW(GetCommandLineW(), &app.argc); LPWSTR * wargv = CommandLineToArgvW(GetCommandLineW(), &app.argc);
app.argv = malloc(sizeof(char *) * app.argc); app.argv = malloc(sizeof(char *) * app.argc);
@ -210,6 +229,8 @@ finish:
bool app_init() bool app_init()
{ {
int shmDevice = option_get_int("os", "shmDevice");
HDEVINFO deviceInfoSet; HDEVINFO deviceInfoSet;
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL; PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData; SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
@ -218,7 +239,7 @@ bool app_init()
memset(&deviceInterfaceData, 0, sizeof(SP_DEVICE_INTERFACE_DATA)); memset(&deviceInterfaceData, 0, sizeof(SP_DEVICE_INTERFACE_DATA));
deviceInterfaceData.cbSize = 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(); DWORD error = GetLastError();
if (error == ERROR_NO_MORE_ITEMS) if (error == ERROR_NO_MORE_ITEMS)

View File

@ -26,6 +26,77 @@ Place, Suite 330, Boston, MA 02111-1307 USA
IVSHMEM * IVSHMEM::m_instance = NULL; 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<PSP_DEVICE_INTERFACE_DETAIL_DATA>(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() : IVSHMEM::IVSHMEM() :
m_initialized(false), m_initialized(false),
m_handle(INVALID_HANDLE_VALUE), m_handle(INVALID_HANDLE_VALUE),
@ -41,7 +112,7 @@ IVSHMEM::~IVSHMEM()
DeInitialize(); DeInitialize();
} }
bool IVSHMEM::Initialize() bool IVSHMEM::Initialize(PCI_DEVICE dev)
{ {
if (m_initialized) if (m_initialized)
DeInitialize(); DeInitialize();
@ -54,23 +125,13 @@ bool IVSHMEM::Initialize()
ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA)); ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
deviceInterfaceData.cbSize = 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; 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) if (!reqSize)
{ {
DEBUG_ERROR("SetupDiGetDeviceInterfaceDetail"); DEBUG_ERROR("SetupDiGetDeviceInterfaceDetail");
@ -83,22 +144,67 @@ bool IVSHMEM::Initialize()
if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, infData, reqSize, NULL, NULL)) if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, infData, reqSize, NULL, NULL))
{ {
DEBUG_ERROR("SetupDiGetDeviceInterfaceDetail"); DEBUG_ERROR("SetupDiGetDeviceInterfaceDetail");
free(infData);
break; 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); m_handle = CreateFile(infData->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0);
if (m_handle == INVALID_HANDLE_VALUE) if (m_handle == INVALID_HANDLE_VALUE)
{ {
DEBUG_ERROR("CreateFile returned INVALID_HANDLE_VALUE"); DEBUG_ERROR("CreateFile returned INVALID_HANDLE_VALUE");
free(infData);
break; break;
} }
m_initialized = true; m_initialized = true;
break; break;
} }
if (infData) DWORD error = GetLastError();
free(infData); 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); SetupDiDestroyDeviceInfoList(deviceInfoSet);
return m_initialized; return m_initialized;

View File

@ -23,6 +23,10 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <windows.h> #include <windows.h>
#include <stdbool.h> #include <stdbool.h>
struct PCI_DEVICE {
BYTE bus, addr, func;
};
class IVSHMEM class IVSHMEM
{ {
public: public:
@ -33,7 +37,9 @@ public:
return m_instance; return m_instance;
} }
bool Initialize(); static void listDevices();
bool Initialize(PCI_DEVICE dev);
void DeInitialize(); void DeInitialize();
bool IsInitialized(); bool IsInitialized();

View File

@ -27,6 +27,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "Util.h" #include "Util.h"
#include "CaptureFactory.h" #include "CaptureFactory.h"
PCI_DEVICE Service::s_dev = {0x13, 0x01, 0x00};
Service::Service() : Service::Service() :
m_initialized(false), m_initialized(false),
m_memory(NULL), m_memory(NULL),
@ -40,7 +42,7 @@ Service::Service() :
m_consoleSessionID = WTSGetActiveConsoleSessionId(); m_consoleSessionID = WTSGetActiveConsoleSessionId();
m_ivshmem = IVSHMEM::Get(); m_ivshmem = IVSHMEM::Get();
if (!m_ivshmem->Initialize()) if (!m_ivshmem->Initialize(s_dev))
throw "IVSHMEM failed to initalize"; throw "IVSHMEM failed to initalize";
if (m_ivshmem->GetSize() < sizeof(KVMFRHeader)) if (m_ivshmem->GetSize() < sizeof(KVMFRHeader))

View File

@ -61,6 +61,11 @@ public:
} }
} }
static void SetDevice(PCI_DEVICE dev)
{
s_dev = dev;
}
bool Initialize(ICapture * captureDevice); bool Initialize(ICapture * captureDevice);
void DeInitialize(); void DeInitialize();
ProcessStatus Process(); ProcessStatus Process();
@ -95,6 +100,7 @@ private:
size_t m_frameSize; size_t m_frameSize;
uint64_t m_dataOffset[MAX_FRAMES]; uint64_t m_dataOffset[MAX_FRAMES];
int m_frameIndex; int m_frameIndex;
static PCI_DEVICE s_dev;
static DWORD WINAPI _CursorThread(LPVOID lpParameter) { return Service::Instance().CursorThread(); } static DWORD WINAPI _CursorThread(LPVOID lpParameter) { return Service::Instance().CursorThread(); }
DWORD CursorThread(); DWORD CursorThread();

View File

@ -196,7 +196,7 @@ int run()
int parseArgs(struct StartupArgs & args) int parseArgs(struct StartupArgs & args)
{ {
int c; int c;
while((c = getopt(__argc, __argv, "hc:o:fl")) != -1) while((c = getopt(__argc, __argv, "hc:o:fld:")) != -1)
{ {
switch (c) switch (c)
{ {
@ -253,6 +253,36 @@ int parseArgs(struct StartupArgs & args)
case 'l': case 'l':
doLicense(); doLicense();
return -1; 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" " -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" " -o Option to pass to the capture device, may be specified multiple times for extra options\n"
" -f Foreground mode\n" " -f Foreground mode\n"
" -l License information\n", " -l License information\n"
" -d Specify the IVSHMEM device with \"<bus>,<slot>,<function>\" or ? to list available\n",
app, app,
app app
); );