Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OVR_Linux_DeviceManager.cpp
Go to the documentation of this file.
1 /************************************************************************************
2 
3 Filename : OVR_Linux_DeviceManager.h
4 Content : Linux implementation of DeviceManager.
5 Created :
6 Authors :
7 
8 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
9 
10 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
12 which is provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
14 
15 You may obtain a copy of the License at
16 
17 http://www.oculusvr.com/licenses/LICENSE-3.1
18 
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24 
25 *************************************************************************************/
26 
28 
29 // Sensor & HMD Factories
30 #include "OVR_LatencyTestImpl.h"
31 #include "OVR_SensorImpl.h"
32 #include "OVR_Linux_HIDDevice.h"
33 #include "OVR_Linux_HMDDevice.h"
34 
35 #include "Kernel/OVR_Timer.h"
36 #include "Kernel/OVR_Std.h"
37 #include "Kernel/OVR_Log.h"
38 
39 namespace OVR { namespace Linux {
40 
41 
42 //-------------------------------------------------------------------------------------
43 // **** Linux::DeviceManager
44 
46 {
47 }
48 
50 {
51 }
52 
54 {
56  return false;
57 
59  if (!pThread || !pThread->Start())
60  return false;
61 
62  // Wait for the thread to be fully up and running.
63  pThread->StartupEvent.Wait();
64 
65  // Do this now that we know the thread's run loop.
67 
68  pCreateDesc->pDevice = this;
69  LogText("OVR::DeviceManager - initialized.\n");
70  return true;
71 }
72 
74 {
75  LogText("OVR::DeviceManager - shutting down.\n");
76 
77  // Set Manager shutdown marker variable; this prevents
78  // any existing DeviceHandle objects from accessing device.
79  pCreateDesc->pLock->pManager = 0;
80 
81  // Push for thread shutdown *WITH NO WAIT*.
82  // This will have the following effect:
83  // - Exit command will get enqueued, which will be executed later on the thread itself.
84  // - Beyond this point, this DeviceManager object may be deleted by our caller.
85  // - Other commands, such as CreateDevice, may execute before ExitCommand, but they will
86  // fail gracefully due to pLock->pManager == 0. Future commands can't be enqued
87  // after pManager is null.
88  // - Once ExitCommand executes, ThreadCommand::Run loop will exit and release the last
89  // reference to the thread object.
90  pThread->PushExitCommand(false);
91  pThread.Clear();
92 
94 }
95 
97 {
98  return pThread;
99 }
100 
102 {
103  return pThread->GetThreadId();
104 }
105 
107 {
108  if ((info->InfoClassType != Device_Manager) &&
109  (info->InfoClassType != Device_None))
110  return false;
111 
112  info->Type = Device_Manager;
113  info->Version = 0;
114  info->ProductName = "DeviceManager";
115  info->Manufacturer = "Oculus VR, Inc.";
116  return true;
117 }
118 
120 {
121  // TBD: Can this be avoided in the future, once proper device notification is in place?
122  pThread->PushCall((DeviceManagerImpl*)this,
124 
126 }
127 
128 
129 //-------------------------------------------------------------------------------------
130 // ***** DeviceManager Thread
131 
133  : Thread(ThreadStackSize)
134 {
135  int result = pipe(CommandFd);
136  OVR_ASSERT(!result);
137  OVR_UNUSED(result);
138 
140 }
141 
143 {
144  if (CommandFd[0])
145  {
147  close(CommandFd[0]);
148  close(CommandFd[1]);
149  }
150 }
151 
153 {
154  struct pollfd pfd;
155  pfd.fd = fd;
156  pfd.events = POLLIN|POLLHUP|POLLERR;
157  pfd.revents = 0;
158 
159  FdNotifiers.PushBack(notify);
160  PollFds.PushBack(pfd);
161 
162  OVR_ASSERT(FdNotifiers.GetSize() == PollFds.GetSize());
163  return true;
164 }
165 
167 {
168  // [0] is reserved for thread commands with notify of null, but we still
169  // can use this function to remove it.
170  for (UPInt i = 0; i < FdNotifiers.GetSize(); i++)
171  {
172  if ((FdNotifiers[i] == notify) && (PollFds[i].fd == fd))
173  {
174  FdNotifiers.RemoveAt(i);
175  PollFds.RemoveAt(i);
176  return true;
177  }
178  }
179  return false;
180 }
181 
182 
183 
185 {
186  ThreadCommand::PopBuffer command;
187 
188  SetThreadName("OVR::DeviceManagerThread");
189  LogText("OVR::DeviceManagerThread - running (ThreadId=%p).\n", GetThreadId());
190 
191  // Signal to the parent thread that initialization has finished.
193 
194  while(!IsExiting())
195  {
196  // PopCommand will reset event on empty queue.
197  if (PopCommand(&command))
198  {
199  command.Execute();
200  }
201  else
202  {
203  bool commands = 0;
204  do
205  {
206  int waitMs = -1;
207 
208  // If devices have time-dependent logic registered, get the longest wait
209  // allowed based on current ticks.
210  if (!TicksNotifiers.IsEmpty())
211  {
212  double timeSeconds = Timer::GetSeconds();
213  unsigned waitAllowed;
214 
215  for (UPInt j = 0; j < TicksNotifiers.GetSize(); j++)
216  {
217  waitAllowed = (unsigned)(TicksNotifiers[j]->OnTicks(timeSeconds) * Timer::MsPerSecond);
218  if (waitAllowed < (unsigned)waitMs)
219  waitMs = waitAllowed;
220  }
221  }
222 
223  // wait until there is data available on one of the devices or the timeout expires
224  int n = poll(&PollFds[0], PollFds.GetSize(), waitMs);
225 
226  if (n > 0)
227  {
228  // Iterate backwards through the list so the ordering will not be
229  // affected if the called object gets removed during the callback
230  // Also, the HID data streams are located toward the back of the list
231  // and servicing them first will allow a disconnect to be handled
232  // and cleaned directly at the device first instead of the general HID monitor
233  for (int i=PollFds.GetSize()-1; i>=0; i--)
234  {
235  if (PollFds[i].revents & POLLERR)
236  {
237  OVR_DEBUG_LOG(("poll: error on [%d]: %d", i, PollFds[i].fd));
238  }
239  else if (PollFds[i].revents & POLLIN)
240  {
241  if (FdNotifiers[i])
242  FdNotifiers[i]->OnEvent(i, PollFds[i].fd);
243  else if (i == 0) // command
244  {
245  char dummy[128];
246  read(PollFds[i].fd, dummy, 128);
247  commands = 1;
248  }
249  }
250 
251  if (PollFds[i].revents & POLLHUP)
252  PollFds[i].events = 0;
253 
254  if (PollFds[i].revents != 0)
255  {
256  n--;
257  if (n == 0)
258  break;
259  }
260  }
261  }
262  } while (PollFds.GetSize() > 0 && !commands);
263  }
264  }
265 
266  LogText("OVR::DeviceManagerThread - exiting (ThreadId=%p).\n", GetThreadId());
267  return 0;
268 }
269 
271 {
272  TicksNotifiers.PushBack(notify);
273  return true;
274 }
275 
277 {
278  for (UPInt i = 0; i < TicksNotifiers.GetSize(); i++)
279  {
280  if (TicksNotifiers[i] == notify)
281  {
282  TicksNotifiers.RemoveAt(i);
283  return true;
284  }
285  }
286  return false;
287 }
288 
289 } // namespace Linux
290 
291 
292 //-------------------------------------------------------------------------------------
293 // ***** Creation
294 
295 
296 // Creates a new DeviceManager and initializes OVR.
298 {
299  if (!System::IsInitialized())
300  {
301  // Use custom message, since Log is not yet installed.
303  LogMessage(Log_Debug, "DeviceManager::Create failed - OVR::System not initialized"); );
304  return 0;
305  }
306 
308 
309  if (manager)
310  {
311  if (manager->Initialize(0))
312  {
313  manager->AddFactory(&LatencyTestDeviceFactory::GetInstance());
314  manager->AddFactory(&SensorDeviceFactory::GetInstance());
315  manager->AddFactory(&Linux::HMDDeviceFactory::GetInstance());
316 
317  manager->AddRef();
318  }
319  else
320  {
321  manager.Clear();
322  }
323 
324  }
325 
326  return manager.GetPtr();
327 }
328 
329 
330 } // namespace OVR
331 
DeviceType Type
Definition: OVR_Device.h:152
void LogText(const char *fmt,...) OVR_LOG_VAARG_ATTRIBUTE(1
OVR_FORCE_INLINE void Clear()
Definition: OVR_RefCount.h:496
bool RemoveSelectFd(Notifier *notify, int fd)
void PushBack(const ValueType &val)
Definition: OVR_Array.h:427
virtual ThreadCommandQueue * GetThreadQueue()
const DeviceType InfoClassType
Definition: OVR_Device.h:149
void SetEvent()
Definition: OVR_Threads.h:160
#define NULL
static LatencyTestDeviceFactory & GetInstance()
Ptr< DeviceCreateDesc > pCreateDesc
unsigned Version
Definition: OVR_Device.h:156
OVR_FORCE_INLINE C * GetPtr() const
Definition: OVR_RefCount.h:506
virtual void SetThreadName(const char *name)
Definition: OVR_Threads.h:349
#define OVR_UNUSED(a)
static SensorDeviceFactory & GetInstance()
#define OVR_DEBUG_STATEMENT(s)
size_t UPInt
Definition: OVR_Types.h:218
Ptr< DeviceManagerThread > pThread
virtual DeviceEnumerator EnumerateDevicesEx(const DeviceEnumerationArgs &args)
virtual bool GetDeviceInfo(DeviceInfo *info) const
static HIDDeviceManager * CreateInternal(DeviceManager *manager)
UPInt GetSize() const
Definition: OVR_Array.h:376
String ProductName
Definition: OVR_Device.h:154
#define OVR_ASSERT(p)
static bool OVR_CDECL IsInitialized()
Definition: OVR_System.cpp:75
bool PopCommand(ThreadCommand::PopBuffer *popBuffer)
static Log * GetDefaultLog()
Definition: OVR_Log.cpp:152
bool AddSelectFd(Notifier *notify, int fd)
virtual bool Initialize(DeviceBase *parent)
static DeviceManager * Create()
void RemoveAt(UPInt index)
Definition: OVR_Array.h:505
Ptr< HIDDeviceManager > HidDeviceManager
void * ThreadId
Definition: OVR_Threads.h:180
ThreadId GetThreadId() const
Definition: OVR_Threads.h:333
static double OVR_STDCALL GetSeconds()
Definition: OVR_Timer.cpp:51
String Manufacturer
Definition: OVR_Device.h:155
#define OVR_DEBUG_LOG(args)
Definition: OVR_Log.h:196
virtual Void EnumerateAllFactoryDevices()
virtual ThreadId GetThreadId() const
static HMDDeviceFactory & GetInstance()
virtual DeviceEnumerator EnumerateDevicesEx(const DeviceEnumerationArgs &args)
virtual bool Initialize(DeviceBase *parent)