mirror of
https://github.com/thinkonmay/sunshine-sdk.git
synced 2025-12-27 15:45:41 +00:00
ivshmem windows
This commit is contained in:
parent
f43c7a2ca4
commit
99d46479bc
@ -1,51 +1,223 @@
|
||||
/**
|
||||
* @file globals.cpp
|
||||
* @brief Implementation for globally accessible variables and functions.
|
||||
*/
|
||||
#include "interprocess.h"
|
||||
#include "logging.h"
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017-2019 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 <thread>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <windows.h>
|
||||
#pragma comment(lib, "user32.lib")
|
||||
#include <SetupAPI.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include "interprocess.h"
|
||||
|
||||
IVSHMEM * IVSHMEM::m_instance = NULL;
|
||||
|
||||
|
||||
void*
|
||||
map_file(char* name)
|
||||
IVSHMEM::IVSHMEM() :
|
||||
m_initialized(false),
|
||||
m_handle(INVALID_HANDLE_VALUE),
|
||||
m_gotSize(false),
|
||||
m_gotPeerID(false),
|
||||
m_gotMemory(false)
|
||||
{
|
||||
HANDLE hMapFile;
|
||||
|
||||
hMapFile = OpenFileMappingA(
|
||||
FILE_MAP_ALL_ACCESS, // read/write access
|
||||
FALSE, // do not inherit the name
|
||||
name); // name of mapping object
|
||||
}
|
||||
|
||||
if (hMapFile == NULL) {
|
||||
BOOST_LOG(error) << "Could not open file mapping object " << GetLastError();
|
||||
return nullptr;
|
||||
}
|
||||
IVSHMEM::~IVSHMEM()
|
||||
{
|
||||
DeInitialize();
|
||||
}
|
||||
|
||||
void* pBuf = MapViewOfFile(hMapFile, // handle to map object
|
||||
FILE_MAP_ALL_ACCESS, // read/write permission
|
||||
0,
|
||||
0,
|
||||
sizeof(Queue));
|
||||
bool IVSHMEM::Initialize()
|
||||
{
|
||||
if (m_initialized)
|
||||
DeInitialize();
|
||||
|
||||
if (pBuf == NULL) {
|
||||
BOOST_LOG(error) << "Could not map view of file (%d) " << GetLastError();
|
||||
CloseHandle(hMapFile);
|
||||
return nullptr;
|
||||
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);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, 0, &deviceInterfaceData) == FALSE)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
if (error == ERROR_NO_MORE_ITEMS)
|
||||
{
|
||||
printf("Unable to enumerate the device, is it attached?");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("SetupDiEnumDeviceInterfaces failed");
|
||||
break;
|
||||
}
|
||||
|
||||
return pBuf;
|
||||
DWORD reqSize = 0;
|
||||
SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &reqSize, NULL);
|
||||
if (!reqSize)
|
||||
{
|
||||
printf("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))
|
||||
{
|
||||
printf("SetupDiGetDeviceInterfaceDetail");
|
||||
break;
|
||||
}
|
||||
|
||||
m_handle = CreateFile(infData->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0);
|
||||
if (m_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("CreateFile returned INVALID_HANDLE_VALUE");
|
||||
break;
|
||||
}
|
||||
|
||||
m_initialized = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (infData)
|
||||
free(infData);
|
||||
|
||||
SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
void IVSHMEM::DeInitialize()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return;
|
||||
|
||||
if (m_gotMemory)
|
||||
{
|
||||
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_RELEASE_MMAP, NULL, 0, NULL, 0, NULL, NULL))
|
||||
printf("DeviceIoControl failed: %d", (int)GetLastError());
|
||||
m_memory = NULL;
|
||||
}
|
||||
|
||||
if (m_handle != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(m_handle);
|
||||
|
||||
m_initialized = false;
|
||||
m_handle = INVALID_HANDLE_VALUE;
|
||||
m_gotSize = false;
|
||||
m_gotPeerID = false;
|
||||
m_gotMemory = false;
|
||||
}
|
||||
|
||||
bool IVSHMEM::IsInitialized()
|
||||
{
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
UINT64 IVSHMEM::GetSize()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return 0;
|
||||
|
||||
if (m_gotSize)
|
||||
return m_size;
|
||||
|
||||
IVSHMEM_SIZE size;
|
||||
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &size, sizeof(IVSHMEM_SIZE), NULL, NULL))
|
||||
{
|
||||
printf("DeviceIoControl Failed: %d", (int)GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_gotSize = true;
|
||||
m_size = static_cast<UINT64>(size);
|
||||
return m_size;
|
||||
}
|
||||
|
||||
UINT16 IVSHMEM::GetPeerID()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return 0;
|
||||
|
||||
if (m_gotPeerID)
|
||||
return m_peerID;
|
||||
|
||||
IVSHMEM_PEERID peerID;
|
||||
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &peerID, sizeof(IVSHMEM_PEERID), NULL, NULL))
|
||||
{
|
||||
printf("DeviceIoControl Failed: %d", (int)GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_gotPeerID = true;
|
||||
m_peerID = static_cast<UINT16>(peerID);
|
||||
return m_peerID;
|
||||
}
|
||||
|
||||
|
||||
void * IVSHMEM::GetMemory()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return NULL;
|
||||
|
||||
if (m_gotMemory)
|
||||
return m_memory;
|
||||
|
||||
// this if define can be removed later once everyone is un the latest version
|
||||
// old versions of the IVSHMEM driver ignore the input argument, as such this
|
||||
// is completely backwards compatible
|
||||
#if defined(IVSHMEM_CACHE_WRITECOMBINED)
|
||||
IVSHMEM_MMAP_CONFIG config;
|
||||
config.cacheMode = IVSHMEM_CACHE_WRITECOMBINED;
|
||||
#endif
|
||||
|
||||
IVSHMEM_MMAP map;
|
||||
ZeroMemory(&map, sizeof(IVSHMEM_MMAP));
|
||||
if (!DeviceIoControl(
|
||||
m_handle,
|
||||
IOCTL_IVSHMEM_REQUEST_MMAP,
|
||||
#if defined(IVSHMEM_CACHE_WRITECOMBINED)
|
||||
&config, sizeof(IVSHMEM_MMAP_CONFIG),
|
||||
#else
|
||||
NULL , 0,
|
||||
#endif
|
||||
&map , sizeof(IVSHMEM_MMAP ),
|
||||
NULL, NULL))
|
||||
{
|
||||
printf("DeviceIoControl Failed: %d", (int)GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_gotSize = true;
|
||||
m_gotPeerID = true;
|
||||
m_gotMemory = true;
|
||||
m_size = static_cast<UINT64>(map.size );
|
||||
m_peerID = static_cast<UINT16>(map.peerID );
|
||||
m_memory = map.ptr;
|
||||
|
||||
return m_memory;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HANDLE IVSHMEM::getHandle()
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
Queue*
|
||||
init_shared_memory(char* data){
|
||||
Queue* memory = (Queue*)map_file(data);
|
||||
return memory;
|
||||
}
|
||||
@ -1,14 +1,127 @@
|
||||
/**
|
||||
* @file globals.h
|
||||
* @brief Header for globally accessible variables and functions.
|
||||
*/
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017-2019 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "thread_pool.h"
|
||||
#include "thread_safe.h"
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
#include <initguid.h>
|
||||
|
||||
#include <smemory.h>
|
||||
DEFINE_GUID (GUID_DEVINTERFACE_IVSHMEM,
|
||||
0xdf576976,0x569d,0x4672,0x95,0xa0,0xf5,0x7e,0x4e,0xa0,0xb2,0x10);
|
||||
// {df576976-569d-4672-95a0-f57e4ea0b210}
|
||||
|
||||
typedef UINT16 IVSHMEM_PEERID;
|
||||
typedef UINT64 IVSHMEM_SIZE;
|
||||
|
||||
#define IVSHMEM_CACHE_NONCACHED 0
|
||||
#define IVSHMEM_CACHE_CACHED 1
|
||||
#define IVSHMEM_CACHE_WRITECOMBINED 2
|
||||
|
||||
/*
|
||||
This structure is for use with the IOCTL_IVSHMEM_REQUEST_MMAP IOCTL
|
||||
*/
|
||||
typedef struct IVSHMEM_MMAP_CONFIG
|
||||
{
|
||||
UINT8 cacheMode; // the caching mode of the mapping, see IVSHMEM_CACHE_* for options
|
||||
}
|
||||
IVSHMEM_MMAP_CONFIG, *PIVSHMEM_MMAP_CONFIG;
|
||||
|
||||
/*
|
||||
This structure is for use with the IOCTL_IVSHMEM_REQUEST_MMAP IOCTL
|
||||
*/
|
||||
typedef struct IVSHMEM_MMAP
|
||||
{
|
||||
IVSHMEM_PEERID peerID; // our peer id
|
||||
IVSHMEM_SIZE size; // the size of the memory region
|
||||
PVOID ptr; // pointer to the memory region
|
||||
UINT16 vectors; // the number of vectors available
|
||||
}
|
||||
IVSHMEM_MMAP, *PIVSHMEM_MMAP;
|
||||
|
||||
/*
|
||||
This structure is for use with the IOCTL_IVSHMEM_RING_DOORBELL IOCTL
|
||||
*/
|
||||
typedef struct IVSHMEM_RING
|
||||
{
|
||||
IVSHMEM_PEERID peerID; // the id of the peer to ring
|
||||
UINT16 vector; // the doorbell to ring
|
||||
}
|
||||
IVSHMEM_RING, *PIVSHMEM_RING;
|
||||
|
||||
/*
|
||||
This structure is for use with the IOCTL_IVSHMEM_REGISTER_EVENT IOCTL
|
||||
|
||||
Please Note:
|
||||
- The IVSHMEM driver has a hard limit of 32 events.
|
||||
- Events that are singleShot are released after they have been set.
|
||||
- At this time repeating events are only released when the driver device
|
||||
handle is closed, closing the event handle doesn't release it from the
|
||||
drivers list. While this won't cause a problem in the driver, it will
|
||||
cause you to run out of event slots.
|
||||
*/
|
||||
typedef struct IVSHMEM_EVENT
|
||||
{
|
||||
UINT16 vector; // the vector that triggers the event
|
||||
HANDLE event; // the event to trigger
|
||||
BOOLEAN singleShot; // set to TRUE if you want the driver to only trigger this event once
|
||||
}
|
||||
IVSHMEM_EVENT, *PIVSHMEM_EVENT;
|
||||
|
||||
#define IOCTL_IVSHMEM_REQUEST_PEERID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IVSHMEM_REQUEST_SIZE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IVSHMEM_REQUEST_MMAP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IVSHMEM_RELEASE_MMAP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IVSHMEM_RING_DOORBELL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IVSHMEM_REGISTER_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
|
||||
Queue*
|
||||
init_shared_memory(char* data);
|
||||
class IVSHMEM
|
||||
{
|
||||
public:
|
||||
IVSHMEM();
|
||||
~IVSHMEM();
|
||||
|
||||
static IVSHMEM * Get()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new IVSHMEM();
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
bool Initialize();
|
||||
void DeInitialize();
|
||||
bool IsInitialized();
|
||||
|
||||
UINT64 GetSize();
|
||||
UINT16 GetPeerID();
|
||||
void * GetMemory();
|
||||
HANDLE getHandle();
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
private:
|
||||
static IVSHMEM * m_instance;
|
||||
bool m_initialized;
|
||||
HANDLE m_handle;
|
||||
UINT64 m_size ; bool m_gotSize ;
|
||||
UINT16 m_peerID ; bool m_gotPeerID;
|
||||
void * m_memory ; bool m_gotMemory;
|
||||
};
|
||||
|
||||
13
src/main.cpp
13
src/main.cpp
@ -8,6 +8,7 @@
|
||||
#include <csignal>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <smemory.h>
|
||||
|
||||
// local includes
|
||||
#include "globals.h"
|
||||
@ -138,16 +139,14 @@ main(int argc, char *argv[]) {
|
||||
queuetype = QueueType::Audio;
|
||||
|
||||
int codec = 0;
|
||||
char* shmid;
|
||||
if (argc == 4) {
|
||||
if (argc == 3) {
|
||||
std::stringstream ss1; ss1 << argv[2];
|
||||
std::string codecs; ss1 >> codecs;
|
||||
shmid = argv[3];
|
||||
if (codecs == "h265")
|
||||
codec = 1;
|
||||
else if (codecs == "av1")
|
||||
codec = 2;
|
||||
} else shmid = argv[2];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -176,8 +175,12 @@ main(int argc, char *argv[]) {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
auto platf_deinit_guard = platf::init();
|
||||
auto queue = init_shared_memory(shmid);
|
||||
|
||||
|
||||
IVSHMEM* ivshmem = new IVSHMEM();
|
||||
auto queue = (Queue*)ivshmem->GetMemory();
|
||||
if (!platf_deinit_guard) {
|
||||
BOOST_LOG(error) << "Platform failed to initialize"sv;
|
||||
return StatusCode::NO_ENCODER_AVAILABLE;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user