-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathsoft_knuckles_provider.cpp
247 lines (214 loc) · 6.56 KB
/
soft_knuckles_provider.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
//////////////////////////////////////////////////////////////////////////////
// soft_knuckles_provider.cpp
//
// This is the "main" of the entire driver. It defines HmdDriverFactory
// below which is the entry point from the vrserver into this shared library.
//
// It also defines SoftKnucklesProvider that waits on a listen socket thread
// thread trigger instantiating the the soft_knuckles_devices. When it
// does receive a new connection, it creates left and right handed
// soft_knuckles_devices.
//
// While it is possible to instantiate the controllers at startup,
// sometimes you may want to start other controllers like the vive controller
// earlier so that you can use a tested and real controller and then add the
// simulated ones in later.
//
#if defined( _WIN32 )
#include <windows.h>
#endif
#include <thread>
#include <string.h>
#include <string>
#include <openvr_driver.h>
#include "soft_knuckles_device.h"
#include "soft_knuckles_debug_handler.h"
#include "socket_notifier.h"
#include "dprintf.h"
using namespace vr;
namespace soft_knuckles
{
static const int NUM_DEVICES = 1;
static const char *listen_address = "127.0.0.1";
static const unsigned short listen_port = 27015;
class SoftKnucklesProvider;
class SoftKnucklesSocketNotifier : public SocketNotifier
{
SoftKnucklesProvider *m_provider;
public:
SoftKnucklesSocketNotifier(SoftKnucklesProvider *p);
void Notify() override;
};
class SoftKnucklesProvider : public IServerTrackedDeviceProvider
{
SoftKnucklesDevice m_knuckles[NUM_DEVICES];
SoftKnucklesDebugHandler m_debug_handler[NUM_DEVICES];
SoftKnucklesSocketNotifier m_notifier;
public:
SoftKnucklesProvider()
: m_notifier(this)
{
dprintf("SoftKnucklesProvider: constructor called\n");
}
virtual EVRInitError Init(vr::IVRDriverContext *pDriverContext) override
{
// NOTE 1: use the driver context. Sets up a big set of globals
VR_INIT_SERVER_DRIVER_CONTEXT(pDriverContext);
dprintf("SoftKnucklesProvider: Init called\n");
if (NUM_DEVICES > 0)
{
m_knuckles[0].Init(TrackedControllerRole_LeftHand, component_definitions_left, NUM_INPUT_COMPONENT_DEFINITIONS,
&m_debug_handler[0]);
}
if (NUM_DEVICES > 1)
{
m_knuckles[1].Init(TrackedControllerRole_RightHand, component_definitions_right, NUM_INPUT_COMPONENT_DEFINITIONS,
&m_debug_handler[1]);
}
m_notifier.StartListening(listen_address, listen_port);
return VRInitError_None;
}
// not virtual:
void AddDevices()
{
for (int i = 0; i < NUM_DEVICES; i++)
{
vr::VRServerDriverHost()->TrackedDeviceAdded(
m_knuckles[i].
get_serial().c_str(),
TrackedDeviceClass_Controller,
&m_knuckles[i]);
}
}
virtual void Cleanup() override
{
dprintf("SoftKnucklesProvider: Cleanup\n");
m_notifier.StopListening();
for (int i = 0; i < NUM_DEVICES; i++)
{
m_knuckles[i].Deactivate();
}
}
virtual const char * const *GetInterfaceVersions() override
{
return vr::k_InterfaceVersions;
}
virtual void RunFrame() override
{
static int i;
if (i++ % 10000 == 0)
{
dprintf("SoftKnucklesProvider: Run Frame %d\n", i);
}
}
virtual bool ShouldBlockStandbyMode() override
{
dprintf("SoftKnucklesProvider: ShouldBlockStandbyMode\n");
return false;
}
virtual void EnterStandby() override
{
dprintf("SoftKnucklesProvider: EnterStandby\n");
for (int i = 0; i < NUM_DEVICES; i++)
{
m_knuckles[i].Deactivate();
}
}
virtual void LeaveStandby() override
{
dprintf("SoftKnucklesProvider: LeaveStandby\n");
//m_knuckles[0].Reactivate();
//m_knuckles[1].Reactivate();
}
};
SoftKnucklesSocketNotifier::SoftKnucklesSocketNotifier(SoftKnucklesProvider *p)
: m_provider(p)
{
}
void SoftKnucklesSocketNotifier::Notify()
{
m_provider->AddDevices();
}
} // end of namespace
bool g_bExiting = false;
class CWatchdogDriver_Sample : public IVRWatchdogProvider
{
public:
CWatchdogDriver_Sample()
{
m_pWatchdogThread = nullptr;
}
virtual EVRInitError Init(vr::IVRDriverContext *pDriverContext);
virtual void Cleanup();
private:
thread * m_pWatchdogThread;
};
void WatchdogThreadFunction()
{
while (!g_bExiting)
{
#if defined( _WINDOWS )
// on windows send the event when the Y key is pressed.
//if ((0x01 & GetAsyncKeyState('Y')) != 0)
{
// Y key was pressed.
vr::VRWatchdogHost()->WatchdogWakeUp();
}
this_thread::sleep_for(chrono::microseconds(500));
#else
// for the other platforms, just send one every five seconds
this_thread::sleep_for(chrono::seconds(5));
vr::VRWatchdogHost()->WatchdogWakeUp();
#endif
}
}
EVRInitError CWatchdogDriver_Sample::Init(vr::IVRDriverContext *pDriverContext)
{
VR_INIT_WATCHDOG_DRIVER_CONTEXT(pDriverContext);
dprintf("SoftKnuckles starting watchdog\n");
// Watchdog mode on Windows starts a thread that listens for the 'Y' key on the keyboard to
// be pressed. A real driver should wait for a system button event or something else from the
// the hardware that signals that the VR system should start up.
g_bExiting = false;
m_pWatchdogThread = new thread(WatchdogThreadFunction);
if (!m_pWatchdogThread)
{
dprintf("Unable to create watchdog thread\n");
return VRInitError_Driver_Failed;
}
return VRInitError_None;
}
void CWatchdogDriver_Sample::Cleanup()
{
g_bExiting = true;
if (m_pWatchdogThread)
{
m_pWatchdogThread->join();
delete m_pWatchdogThread;
m_pWatchdogThread = nullptr;
}
}
#if defined(_WIN32)
#define HMD_DLL_EXPORT extern "C" __declspec( dllexport )
#define HMD_DLL_IMPORT extern "C" __declspec( dllimport )
#elif defined(__GNUC__) || defined(COMPILER_GCC) || defined(__APPLE__)
#define HMD_DLL_EXPORT extern "C" __attribute__((visibility("default")))
#define HMD_DLL_IMPORT extern "C"
#else
#error "Unsupported Platform."
#endif
HMD_DLL_EXPORT void *HmdDriverFactory(const char *pInterfaceName, int *pReturnCode)
{
dprintf("HmdDriverFactory %s\n", pInterfaceName);
static soft_knuckles::SoftKnucklesProvider s_knuckles_provider; // single instance of the provider
static CWatchdogDriver_Sample s_watchdogDriverNull; // this is from sample code.
if (0 == strcmp(IServerTrackedDeviceProvider_Version, pInterfaceName))
{
return &s_knuckles_provider;
}
if (0 == strcmp(IVRWatchdogProvider_Version, pInterfaceName))
{
return &s_watchdogDriverNull;
}
return nullptr;
}