mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-10-14 11:28:11 +00:00
[common] move ivshmem code into the common library
This commit is contained in:
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
|
||||
project(lg_common_platform_code LANGUAGES C)
|
||||
|
||||
include_directories(
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
${PROJECT_TOP}/vendor/ivshmem
|
||||
)
|
||||
|
||||
add_library(lg_common_platform_code STATIC
|
||||
@@ -11,4 +11,5 @@ add_library(lg_common_platform_code STATIC
|
||||
thread.c
|
||||
event.c
|
||||
windebug.c
|
||||
ivshmem.c
|
||||
)
|
||||
|
153
common/src/platform/windows/ivshmem.c
Normal file
153
common/src/platform/windows/ivshmem.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "common/ivshmem.h"
|
||||
#include "common/option.h"
|
||||
#include "common/windebug.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include "ivshmem.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <setupapi.h>
|
||||
#include <io.h>
|
||||
|
||||
struct IVSHMEMInfo
|
||||
{
|
||||
HANDLE handle;
|
||||
};
|
||||
|
||||
void ivshmemOptionsInit()
|
||||
{
|
||||
static struct Option options[] = {
|
||||
{
|
||||
.module = "os",
|
||||
.name = "shmDevice",
|
||||
.description = "The IVSHMEM device to use",
|
||||
.type = OPTION_TYPE_INT,
|
||||
.value.x_int = 0
|
||||
},
|
||||
{0}
|
||||
};
|
||||
|
||||
option_register(options);
|
||||
}
|
||||
|
||||
bool ivshmemOpen(struct IVSHMEM * dev)
|
||||
{
|
||||
assert(dev);
|
||||
|
||||
HANDLE devHandle;
|
||||
|
||||
{
|
||||
HDEVINFO devInfoSet;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL;
|
||||
SP_DEVICE_INTERFACE_DATA devInterfaceData = {0};
|
||||
|
||||
devInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
|
||||
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
|
||||
const int shmDevice = option_get_int("os", "shmDevice");
|
||||
if (SetupDiEnumDeviceInterfaces(devInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, shmDevice, &devInterfaceData) == FALSE)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
if (error == ERROR_NO_MORE_ITEMS)
|
||||
{
|
||||
DEBUG_WINERROR("Unable to enumerate the device, is it attached?", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_WINERROR("SetupDiEnumDeviceInterfaces failed", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD reqSize = 0;
|
||||
SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterfaceData, NULL, 0, &reqSize, NULL);
|
||||
if (!reqSize)
|
||||
{
|
||||
DEBUG_WINERROR("SetupDiGetDeviceInterfaceDetail", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
infData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)calloc(reqSize, 1);
|
||||
infData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
if (!SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterfaceData, infData, reqSize, NULL, NULL))
|
||||
{
|
||||
free(infData);
|
||||
DEBUG_WINERROR("SetupDiGetDeviceInterfaceDetail", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
devHandle = CreateFile(infData->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0);
|
||||
if (devHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SetupDiDestroyDeviceInfoList(devInfoSet);
|
||||
free(infData);
|
||||
DEBUG_WINERROR("CreateFile returned INVALID_HANDLE_VALUE", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
free(infData);
|
||||
SetupDiDestroyDeviceInfoList(devInfoSet);
|
||||
}
|
||||
|
||||
IVSHMEM_SIZE size;
|
||||
if (!DeviceIoControl(devHandle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &size, sizeof(IVSHMEM_SIZE), NULL, NULL))
|
||||
{
|
||||
DEBUG_WINERROR("DeviceIoControl Failed", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
IVSHMEM_MMAP_CONFIG config = { .cacheMode = IVSHMEM_CACHE_WRITECOMBINED };
|
||||
IVSHMEM_MMAP map = { 0 };
|
||||
if (!DeviceIoControl(
|
||||
devHandle,
|
||||
IOCTL_IVSHMEM_REQUEST_MMAP,
|
||||
&config, sizeof(IVSHMEM_MMAP_CONFIG),
|
||||
&map , sizeof(IVSHMEM_MMAP),
|
||||
NULL, NULL))
|
||||
{
|
||||
DEBUG_WINERROR("DeviceIoControl Failed", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
struct IVSHMEMInfo * info =
|
||||
(struct IVSHMEMInfo *)malloc(sizeof(struct IVSHMEMInfo));
|
||||
|
||||
info->handle = devHandle;
|
||||
|
||||
dev->opaque = info;
|
||||
dev->size = (unsigned int)size;
|
||||
dev->mem = map.ptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ivshmemClose(struct IVSHMEM * dev)
|
||||
{
|
||||
assert(dev);
|
||||
|
||||
struct IVSHMEMInfo * info =
|
||||
(struct IVSHMEMInfo *)dev->opaque;
|
||||
|
||||
if (!DeviceIoControl(info->handle, IOCTL_IVSHMEM_RELEASE_MMAP, NULL, 0, NULL, 0, NULL, NULL))
|
||||
DEBUG_WINERROR("DeviceIoControl failed", GetLastError());
|
||||
|
||||
free(info);
|
||||
}
|
Reference in New Issue
Block a user