rev |
line source |
nuclear@1
|
1 /************************************************************************************
|
nuclear@1
|
2 Filename : OVR_OSX_HIDDevice.cpp
|
nuclear@1
|
3 Content : OSX HID device implementation.
|
nuclear@1
|
4 Created : February 26, 2013
|
nuclear@1
|
5 Authors : Lee Cooper
|
nuclear@1
|
6
|
nuclear@1
|
7 Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
|
nuclear@1
|
8
|
nuclear@1
|
9 Use of this software is subject to the terms of the Oculus license
|
nuclear@1
|
10 agreement provided at the time of installation or download, or which
|
nuclear@1
|
11 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@1
|
12
|
nuclear@1
|
13 *************************************************************************************/
|
nuclear@1
|
14
|
nuclear@1
|
15 #include "OVR_OSX_HIDDevice.h"
|
nuclear@1
|
16
|
nuclear@1
|
17 #include <IOKit/usb/IOUSBLib.h>
|
nuclear@1
|
18
|
nuclear@1
|
19 namespace OVR { namespace OSX {
|
nuclear@1
|
20
|
nuclear@1
|
21 static const UInt32 MAX_QUEUED_INPUT_REPORTS = 5;
|
nuclear@1
|
22
|
nuclear@1
|
23 //-------------------------------------------------------------------------------------
|
nuclear@1
|
24 // **** OSX::DeviceManager
|
nuclear@1
|
25
|
nuclear@1
|
26 HIDDeviceManager::HIDDeviceManager(DeviceManager* manager)
|
nuclear@1
|
27 : DevManager(manager)
|
nuclear@1
|
28 {
|
nuclear@1
|
29 HIDManager = NULL;
|
nuclear@1
|
30 }
|
nuclear@1
|
31
|
nuclear@1
|
32 HIDDeviceManager::~HIDDeviceManager()
|
nuclear@1
|
33 {
|
nuclear@1
|
34 }
|
nuclear@1
|
35
|
nuclear@1
|
36 CFRunLoopRef HIDDeviceManager::getRunLoop()
|
nuclear@1
|
37 {
|
nuclear@1
|
38 if (DevManager != NULL)
|
nuclear@1
|
39 {
|
nuclear@1
|
40 return DevManager->pThread->GetRunLoop();
|
nuclear@1
|
41 }
|
nuclear@1
|
42
|
nuclear@1
|
43 return CFRunLoopGetCurrent();
|
nuclear@1
|
44 }
|
nuclear@1
|
45
|
nuclear@1
|
46 bool HIDDeviceManager::initializeManager()
|
nuclear@1
|
47 {
|
nuclear@1
|
48 if (HIDManager != NULL)
|
nuclear@1
|
49 {
|
nuclear@1
|
50 return true;
|
nuclear@1
|
51 }
|
nuclear@1
|
52
|
nuclear@1
|
53 HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
nuclear@1
|
54
|
nuclear@1
|
55 if (!HIDManager)
|
nuclear@1
|
56 {
|
nuclear@1
|
57 return false;
|
nuclear@1
|
58 }
|
nuclear@1
|
59
|
nuclear@1
|
60 // Create a Matching Dictionary
|
nuclear@1
|
61 CFMutableDictionaryRef matchDict =
|
nuclear@1
|
62 CFDictionaryCreateMutable(kCFAllocatorDefault,
|
nuclear@1
|
63 2,
|
nuclear@1
|
64 &kCFTypeDictionaryKeyCallBacks,
|
nuclear@1
|
65 &kCFTypeDictionaryValueCallBacks);
|
nuclear@1
|
66
|
nuclear@1
|
67 // Specify a device manufacturer in the Matching Dictionary
|
nuclear@1
|
68 UInt32 vendorId = Oculus_VendorId;
|
nuclear@1
|
69 CFNumberRef vendorIdRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vendorId);
|
nuclear@1
|
70 CFDictionarySetValue(matchDict,
|
nuclear@1
|
71 CFSTR(kIOHIDVendorIDKey),
|
nuclear@1
|
72 vendorIdRef);
|
nuclear@1
|
73 // Register the Matching Dictionary to the HID Manager
|
nuclear@1
|
74 IOHIDManagerSetDeviceMatching(HIDManager, matchDict);
|
nuclear@1
|
75 CFRelease(vendorIdRef);
|
nuclear@1
|
76 CFRelease(matchDict);
|
nuclear@1
|
77
|
nuclear@1
|
78 // Register a callback for USB device detection with the HID Manager
|
nuclear@1
|
79 IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, &staticDeviceMatchingCallback, this);
|
nuclear@1
|
80
|
nuclear@1
|
81 IOHIDManagerScheduleWithRunLoop(HIDManager, getRunLoop(), kCFRunLoopDefaultMode);
|
nuclear@1
|
82
|
nuclear@1
|
83 return true;
|
nuclear@1
|
84 }
|
nuclear@1
|
85
|
nuclear@1
|
86 bool HIDDeviceManager::Initialize()
|
nuclear@1
|
87 {
|
nuclear@1
|
88 return initializeManager();
|
nuclear@1
|
89 }
|
nuclear@1
|
90
|
nuclear@1
|
91 void HIDDeviceManager::Shutdown()
|
nuclear@1
|
92 {
|
nuclear@1
|
93 OVR_ASSERT_LOG(HIDManager, ("Should have called 'Initialize' before 'Shutdown'."));
|
nuclear@1
|
94 CFRelease(HIDManager);
|
nuclear@1
|
95
|
nuclear@1
|
96 LogText("OVR::OSX::HIDDeviceManager - shutting down.\n");
|
nuclear@1
|
97 }
|
nuclear@1
|
98
|
nuclear@1
|
99 bool HIDDeviceManager::getIntProperty(IOHIDDeviceRef device, CFStringRef propertyName, SInt32* pResult)
|
nuclear@1
|
100 {
|
nuclear@1
|
101
|
nuclear@1
|
102 CFTypeRef ref = IOHIDDeviceGetProperty(device, propertyName);
|
nuclear@1
|
103
|
nuclear@1
|
104 if (!ref)
|
nuclear@1
|
105 {
|
nuclear@1
|
106 return false;
|
nuclear@1
|
107 }
|
nuclear@1
|
108
|
nuclear@1
|
109 if (CFGetTypeID(ref) != CFNumberGetTypeID())
|
nuclear@1
|
110 {
|
nuclear@1
|
111 return false;
|
nuclear@1
|
112 }
|
nuclear@1
|
113
|
nuclear@1
|
114 CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, pResult);
|
nuclear@1
|
115
|
nuclear@1
|
116 return true;
|
nuclear@1
|
117 }
|
nuclear@1
|
118
|
nuclear@1
|
119 bool HIDDeviceManager::initVendorProductVersion(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
|
nuclear@1
|
120 {
|
nuclear@1
|
121
|
nuclear@1
|
122 if (!getVendorId(device, &(pDevDesc->VendorId)))
|
nuclear@1
|
123 {
|
nuclear@1
|
124 return false;
|
nuclear@1
|
125 }
|
nuclear@1
|
126
|
nuclear@1
|
127 if (!getProductId(device, &(pDevDesc->ProductId)))
|
nuclear@1
|
128 {
|
nuclear@1
|
129 return false;
|
nuclear@1
|
130 }
|
nuclear@1
|
131
|
nuclear@1
|
132 return true;
|
nuclear@1
|
133 }
|
nuclear@1
|
134
|
nuclear@1
|
135 bool HIDDeviceManager::initUsage(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
|
nuclear@1
|
136 {
|
nuclear@1
|
137
|
nuclear@1
|
138 SInt32 result;
|
nuclear@1
|
139
|
nuclear@1
|
140 if (!getIntProperty(device, CFSTR(kIOHIDPrimaryUsagePageKey), &result))
|
nuclear@1
|
141 {
|
nuclear@1
|
142 return false;
|
nuclear@1
|
143 }
|
nuclear@1
|
144
|
nuclear@1
|
145 pDevDesc->UsagePage = result;
|
nuclear@1
|
146
|
nuclear@1
|
147
|
nuclear@1
|
148 if (!getIntProperty(device, CFSTR(kIOHIDPrimaryUsageKey), &result))
|
nuclear@1
|
149 {
|
nuclear@1
|
150 return false;
|
nuclear@1
|
151 }
|
nuclear@1
|
152
|
nuclear@1
|
153 pDevDesc->Usage = result;
|
nuclear@1
|
154
|
nuclear@1
|
155 return true;
|
nuclear@1
|
156 }
|
nuclear@1
|
157
|
nuclear@1
|
158 bool HIDDeviceManager::initSerialNumber(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
|
nuclear@1
|
159 {
|
nuclear@1
|
160 return getSerialNumberString(device, &(pDevDesc->SerialNumber));
|
nuclear@1
|
161 }
|
nuclear@1
|
162
|
nuclear@1
|
163 bool HIDDeviceManager::initStrings(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
|
nuclear@1
|
164 {
|
nuclear@1
|
165
|
nuclear@1
|
166 // Regardless of whether they fail we'll try and get the remaining.
|
nuclear@1
|
167 getStringProperty(device, CFSTR(kIOHIDManufacturerKey), &(pDevDesc->Manufacturer));
|
nuclear@1
|
168 getStringProperty(device, CFSTR(kIOHIDProductKey), &(pDevDesc->Product));
|
nuclear@1
|
169
|
nuclear@1
|
170 return true;
|
nuclear@1
|
171 }
|
nuclear@1
|
172
|
nuclear@1
|
173 bool HIDDeviceManager::getStringProperty(IOHIDDeviceRef device,
|
nuclear@1
|
174 CFStringRef propertyName,
|
nuclear@1
|
175 String* pResult)
|
nuclear@1
|
176 {
|
nuclear@1
|
177
|
nuclear@1
|
178 CFStringRef str = (CFStringRef) IOHIDDeviceGetProperty(device, propertyName);
|
nuclear@1
|
179
|
nuclear@1
|
180 if (!str)
|
nuclear@1
|
181 {
|
nuclear@1
|
182 return false;
|
nuclear@1
|
183 }
|
nuclear@1
|
184
|
nuclear@1
|
185 CFIndex length = CFStringGetLength(str);
|
nuclear@1
|
186 CFRange range = CFRangeMake(0, length);
|
nuclear@1
|
187
|
nuclear@1
|
188 // Test the conversion first to get required buffer size.
|
nuclear@1
|
189 CFIndex bufferLength;
|
nuclear@1
|
190 CFIndex numberOfChars = CFStringGetBytes(str,
|
nuclear@1
|
191 range,
|
nuclear@1
|
192 kCFStringEncodingUTF8,
|
nuclear@1
|
193 (char) '?',
|
nuclear@1
|
194 FALSE,
|
nuclear@1
|
195 NULL,
|
nuclear@1
|
196 0,
|
nuclear@1
|
197 &bufferLength);
|
nuclear@1
|
198
|
nuclear@1
|
199 if (numberOfChars == 0)
|
nuclear@1
|
200 {
|
nuclear@1
|
201 return false;
|
nuclear@1
|
202 }
|
nuclear@1
|
203
|
nuclear@1
|
204 // Now allocate buffer.
|
nuclear@1
|
205 char* buffer = new char[bufferLength+1];
|
nuclear@1
|
206
|
nuclear@1
|
207 numberOfChars = CFStringGetBytes(str,
|
nuclear@1
|
208 range,
|
nuclear@1
|
209 kCFStringEncodingUTF8,
|
nuclear@1
|
210 (char) '?',
|
nuclear@1
|
211 FALSE,
|
nuclear@1
|
212 (UInt8*) buffer,
|
nuclear@1
|
213 bufferLength,
|
nuclear@1
|
214 NULL);
|
nuclear@1
|
215 OVR_ASSERT_LOG(numberOfChars != 0, ("CFStringGetBytes failed."));
|
nuclear@1
|
216
|
nuclear@1
|
217 buffer[bufferLength] = '\0';
|
nuclear@1
|
218 *pResult = String(buffer);
|
nuclear@1
|
219
|
nuclear@1
|
220 return true;
|
nuclear@1
|
221 }
|
nuclear@1
|
222
|
nuclear@1
|
223 bool HIDDeviceManager::getVendorId(IOHIDDeviceRef device, UInt16* pResult)
|
nuclear@1
|
224 {
|
nuclear@1
|
225 SInt32 result;
|
nuclear@1
|
226
|
nuclear@1
|
227 if (!getIntProperty(device, CFSTR(kIOHIDVendorIDKey), &result))
|
nuclear@1
|
228 {
|
nuclear@1
|
229 return false;
|
nuclear@1
|
230 }
|
nuclear@1
|
231
|
nuclear@1
|
232 *pResult = result;
|
nuclear@1
|
233
|
nuclear@1
|
234 return true;
|
nuclear@1
|
235 }
|
nuclear@1
|
236
|
nuclear@1
|
237 bool HIDDeviceManager::getProductId(IOHIDDeviceRef device, UInt16* pResult)
|
nuclear@1
|
238 {
|
nuclear@1
|
239 SInt32 result;
|
nuclear@1
|
240
|
nuclear@1
|
241 if (!getIntProperty(device, CFSTR(kIOHIDProductIDKey), &result))
|
nuclear@1
|
242 {
|
nuclear@1
|
243 return false;
|
nuclear@1
|
244 }
|
nuclear@1
|
245
|
nuclear@1
|
246 *pResult = result;
|
nuclear@1
|
247
|
nuclear@1
|
248 return true;
|
nuclear@1
|
249 }
|
nuclear@1
|
250
|
nuclear@1
|
251 bool HIDDeviceManager::getLocationId(IOHIDDeviceRef device, SInt32* pResult)
|
nuclear@1
|
252 {
|
nuclear@1
|
253 SInt32 result;
|
nuclear@1
|
254
|
nuclear@1
|
255 if (!getIntProperty(device, CFSTR(kIOHIDLocationIDKey), &result))
|
nuclear@1
|
256 {
|
nuclear@1
|
257 return false;
|
nuclear@1
|
258 }
|
nuclear@1
|
259
|
nuclear@1
|
260 *pResult = result;
|
nuclear@1
|
261
|
nuclear@1
|
262 return true;
|
nuclear@1
|
263 }
|
nuclear@1
|
264
|
nuclear@1
|
265 bool HIDDeviceManager::getSerialNumberString(IOHIDDeviceRef device, String* pResult)
|
nuclear@1
|
266 {
|
nuclear@1
|
267
|
nuclear@1
|
268 if (!getStringProperty(device, CFSTR(kIOHIDSerialNumberKey), pResult))
|
nuclear@1
|
269 {
|
nuclear@1
|
270 return false;
|
nuclear@1
|
271 }
|
nuclear@1
|
272
|
nuclear@1
|
273 return true;
|
nuclear@1
|
274 }
|
nuclear@1
|
275
|
nuclear@1
|
276 bool HIDDeviceManager::getPath(IOHIDDeviceRef device, String* pPath)
|
nuclear@1
|
277 {
|
nuclear@1
|
278
|
nuclear@1
|
279 String transport;
|
nuclear@1
|
280 if (!getStringProperty(device, CFSTR(kIOHIDTransportKey), &transport))
|
nuclear@1
|
281 {
|
nuclear@1
|
282 return false;
|
nuclear@1
|
283 }
|
nuclear@1
|
284
|
nuclear@1
|
285 UInt16 vendorId;
|
nuclear@1
|
286 if (!getVendorId(device, &vendorId))
|
nuclear@1
|
287 {
|
nuclear@1
|
288 return false;
|
nuclear@1
|
289 }
|
nuclear@1
|
290
|
nuclear@1
|
291 UInt16 productId;
|
nuclear@1
|
292 if (!getProductId(device, &productId))
|
nuclear@1
|
293 {
|
nuclear@1
|
294 return false;
|
nuclear@1
|
295 }
|
nuclear@1
|
296
|
nuclear@1
|
297 String serialNumber;
|
nuclear@1
|
298 if (!getSerialNumberString(device, &serialNumber))
|
nuclear@1
|
299 {
|
nuclear@1
|
300 return false;
|
nuclear@1
|
301 }
|
nuclear@1
|
302
|
nuclear@1
|
303
|
nuclear@1
|
304 StringBuffer buffer;
|
nuclear@1
|
305 buffer.AppendFormat("%s:vid=%04hx:pid=%04hx:ser=%s",
|
nuclear@1
|
306 transport.ToCStr(),
|
nuclear@1
|
307 vendorId,
|
nuclear@1
|
308 productId,
|
nuclear@1
|
309 serialNumber.ToCStr());
|
nuclear@1
|
310
|
nuclear@1
|
311 *pPath = String(buffer);
|
nuclear@1
|
312
|
nuclear@1
|
313 return true;
|
nuclear@1
|
314 }
|
nuclear@1
|
315
|
nuclear@1
|
316 bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor)
|
nuclear@1
|
317 {
|
nuclear@1
|
318 if (!initializeManager())
|
nuclear@1
|
319 {
|
nuclear@1
|
320 return false;
|
nuclear@1
|
321 }
|
nuclear@1
|
322
|
nuclear@1
|
323
|
nuclear@1
|
324 CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager);
|
nuclear@1
|
325 if (!deviceSet)
|
nuclear@1
|
326 return false;
|
nuclear@1
|
327
|
nuclear@1
|
328 CFIndex deviceCount = CFSetGetCount(deviceSet);
|
nuclear@1
|
329
|
nuclear@1
|
330 // Allocate a block of memory and read the set into it.
|
nuclear@1
|
331 IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount);
|
nuclear@1
|
332 CFSetGetValues(deviceSet, (const void **) devices);
|
nuclear@1
|
333
|
nuclear@1
|
334
|
nuclear@1
|
335 // Iterate over devices.
|
nuclear@1
|
336 for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
|
nuclear@1
|
337 {
|
nuclear@1
|
338 IOHIDDeviceRef hidDev = devices[deviceIndex];
|
nuclear@1
|
339
|
nuclear@1
|
340 if (!hidDev)
|
nuclear@1
|
341 {
|
nuclear@1
|
342 continue;
|
nuclear@1
|
343 }
|
nuclear@1
|
344
|
nuclear@1
|
345 HIDDeviceDesc devDesc;
|
nuclear@1
|
346
|
nuclear@1
|
347 if (getPath(hidDev, &(devDesc.Path)) &&
|
nuclear@1
|
348 initVendorProductVersion(hidDev, &devDesc) &&
|
nuclear@1
|
349 enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId) &&
|
nuclear@1
|
350 initUsage(hidDev, &devDesc))
|
nuclear@1
|
351 {
|
nuclear@1
|
352 initStrings(hidDev, &devDesc);
|
nuclear@1
|
353 initSerialNumber(hidDev, &devDesc);
|
nuclear@1
|
354
|
nuclear@1
|
355 // Look for the device to check if it is already opened.
|
nuclear@1
|
356 Ptr<DeviceCreateDesc> existingDevice = DevManager->FindHIDDevice(devDesc);
|
nuclear@1
|
357 // if device exists and it is opened then most likely the CreateHIDFile
|
nuclear@1
|
358 // will fail; therefore, we just set Enumerated to 'true' and continue.
|
nuclear@1
|
359 if (existingDevice && existingDevice->pDevice)
|
nuclear@1
|
360 {
|
nuclear@1
|
361 existingDevice->Enumerated = true;
|
nuclear@1
|
362 continue;
|
nuclear@1
|
363 }
|
nuclear@1
|
364
|
nuclear@1
|
365 // Construct minimal device that the visitor callback can get feature reports from.
|
nuclear@1
|
366 OSX::HIDDevice device(this, hidDev);
|
nuclear@1
|
367
|
nuclear@1
|
368 enumVisitor->Visit(device, devDesc);
|
nuclear@1
|
369 }
|
nuclear@1
|
370 }
|
nuclear@1
|
371
|
nuclear@1
|
372 OVR_FREE(devices);
|
nuclear@1
|
373 CFRelease(deviceSet);
|
nuclear@1
|
374
|
nuclear@1
|
375 return true;
|
nuclear@1
|
376 }
|
nuclear@1
|
377
|
nuclear@1
|
378 OVR::HIDDevice* HIDDeviceManager::Open(const String& path)
|
nuclear@1
|
379 {
|
nuclear@1
|
380
|
nuclear@1
|
381 Ptr<OSX::HIDDevice> device = *new OSX::HIDDevice(this);
|
nuclear@1
|
382
|
nuclear@1
|
383 if (!device->HIDInitialize(path))
|
nuclear@1
|
384 {
|
nuclear@1
|
385 return NULL;
|
nuclear@1
|
386 }
|
nuclear@1
|
387
|
nuclear@1
|
388 device->AddRef();
|
nuclear@1
|
389
|
nuclear@1
|
390 return device;
|
nuclear@1
|
391 }
|
nuclear@1
|
392
|
nuclear@1
|
393 bool HIDDeviceManager::getFullDesc(IOHIDDeviceRef device, HIDDeviceDesc* desc)
|
nuclear@1
|
394 {
|
nuclear@1
|
395
|
nuclear@1
|
396 if (!initVendorProductVersion(device, desc))
|
nuclear@1
|
397 {
|
nuclear@1
|
398 return false;
|
nuclear@1
|
399 }
|
nuclear@1
|
400
|
nuclear@1
|
401 if (!initUsage(device, desc))
|
nuclear@1
|
402 {
|
nuclear@1
|
403 return false;
|
nuclear@1
|
404 }
|
nuclear@1
|
405
|
nuclear@1
|
406 if (!initSerialNumber(device, desc))
|
nuclear@1
|
407 {
|
nuclear@1
|
408 return false;
|
nuclear@1
|
409 }
|
nuclear@1
|
410
|
nuclear@1
|
411 initStrings(device, desc);
|
nuclear@1
|
412
|
nuclear@1
|
413 return true;
|
nuclear@1
|
414 }
|
nuclear@1
|
415
|
nuclear@1
|
416 // New USB device specified in the matching dictionary has been added (callback function)
|
nuclear@1
|
417 void HIDDeviceManager::staticDeviceMatchingCallback(void *inContext,
|
nuclear@1
|
418 IOReturn inResult,
|
nuclear@1
|
419 void *inSender,
|
nuclear@1
|
420 IOHIDDeviceRef inIOHIDDeviceRef)
|
nuclear@1
|
421 {
|
nuclear@1
|
422 HIDDeviceManager* hidMgr = static_cast<HIDDeviceManager*>(inContext);
|
nuclear@1
|
423 HIDDeviceDesc hidDevDesc;
|
nuclear@1
|
424 hidMgr->getPath(inIOHIDDeviceRef, &hidDevDesc.Path);
|
nuclear@1
|
425 hidMgr->getFullDesc(inIOHIDDeviceRef, &hidDevDesc);
|
nuclear@1
|
426
|
nuclear@1
|
427 hidMgr->DevManager->DetectHIDDevice(hidDevDesc);
|
nuclear@1
|
428 }
|
nuclear@1
|
429
|
nuclear@1
|
430 //-------------------------------------------------------------------------------------
|
nuclear@1
|
431 // **** OSX::HIDDevice
|
nuclear@1
|
432
|
nuclear@1
|
433 HIDDevice::HIDDevice(HIDDeviceManager* manager)
|
nuclear@1
|
434 : HIDManager(manager), InMinimalMode(false)
|
nuclear@1
|
435 {
|
nuclear@1
|
436 Device = NULL;
|
nuclear@1
|
437 RepluggedNotificationPort = 0;
|
nuclear@1
|
438 }
|
nuclear@1
|
439
|
nuclear@1
|
440 // This is a minimal constructor used during enumeration for us to pass
|
nuclear@1
|
441 // a HIDDevice to the visit function (so that it can query feature reports).
|
nuclear@1
|
442 HIDDevice::HIDDevice(HIDDeviceManager* manager, IOHIDDeviceRef device)
|
nuclear@1
|
443 : HIDManager(manager), Device(device), InMinimalMode(true)
|
nuclear@1
|
444 {
|
nuclear@1
|
445 RepluggedNotificationPort = 0;
|
nuclear@1
|
446 }
|
nuclear@1
|
447
|
nuclear@1
|
448 HIDDevice::~HIDDevice()
|
nuclear@1
|
449 {
|
nuclear@1
|
450 if (!InMinimalMode)
|
nuclear@1
|
451 {
|
nuclear@1
|
452 HIDShutdown();
|
nuclear@1
|
453 }
|
nuclear@1
|
454 }
|
nuclear@1
|
455
|
nuclear@1
|
456 bool HIDDevice::HIDInitialize(const String& path)
|
nuclear@1
|
457 {
|
nuclear@1
|
458
|
nuclear@1
|
459 DevDesc.Path = path;
|
nuclear@1
|
460
|
nuclear@1
|
461 if (!openDevice())
|
nuclear@1
|
462 {
|
nuclear@1
|
463 LogText("OVR::OSX::HIDDevice - Failed to open HIDDevice: %s", path.ToCStr());
|
nuclear@1
|
464 return false;
|
nuclear@1
|
465 }
|
nuclear@1
|
466
|
nuclear@1
|
467 // Setup notification for when a device is unplugged and plugged back in.
|
nuclear@1
|
468 if (!setupDevicePluggedInNotification())
|
nuclear@1
|
469 {
|
nuclear@1
|
470 LogText("OVR::OSX::HIDDevice - Failed to setup notification for when device plugged back in.");
|
nuclear@1
|
471 closeDevice(false);
|
nuclear@1
|
472 return false;
|
nuclear@1
|
473 }
|
nuclear@1
|
474
|
nuclear@1
|
475 HIDManager->DevManager->pThread->AddTicksNotifier(this);
|
nuclear@1
|
476
|
nuclear@1
|
477
|
nuclear@1
|
478 LogText("OVR::OSX::HIDDevice - Opened '%s'\n"
|
nuclear@1
|
479 " Manufacturer:'%s' Product:'%s' Serial#:'%s'\n",
|
nuclear@1
|
480 DevDesc.Path.ToCStr(),
|
nuclear@1
|
481 DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(),
|
nuclear@1
|
482 DevDesc.SerialNumber.ToCStr());
|
nuclear@1
|
483
|
nuclear@1
|
484 return true;
|
nuclear@1
|
485 }
|
nuclear@1
|
486
|
nuclear@1
|
487 bool HIDDevice::initInfo()
|
nuclear@1
|
488 {
|
nuclear@1
|
489 // Device must have been successfully opened.
|
nuclear@1
|
490 OVR_ASSERT(Device);
|
nuclear@1
|
491
|
nuclear@1
|
492
|
nuclear@1
|
493 // Get report lengths.
|
nuclear@1
|
494 SInt32 bufferLength;
|
nuclear@1
|
495 bool getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxInputReportSizeKey), &bufferLength);
|
nuclear@1
|
496 OVR_ASSERT(getResult);
|
nuclear@1
|
497 InputReportBufferLength = (UInt16) bufferLength;
|
nuclear@1
|
498
|
nuclear@1
|
499 getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxOutputReportSizeKey), &bufferLength);
|
nuclear@1
|
500 OVR_ASSERT(getResult);
|
nuclear@1
|
501 OutputReportBufferLength = (UInt16) bufferLength;
|
nuclear@1
|
502
|
nuclear@1
|
503 getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxFeatureReportSizeKey), &bufferLength);
|
nuclear@1
|
504 OVR_ASSERT(getResult);
|
nuclear@1
|
505 FeatureReportBufferLength = (UInt16) bufferLength;
|
nuclear@1
|
506
|
nuclear@1
|
507
|
nuclear@1
|
508 if (ReadBufferSize < InputReportBufferLength)
|
nuclear@1
|
509 {
|
nuclear@1
|
510 OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
|
nuclear@1
|
511 return false;
|
nuclear@1
|
512 }
|
nuclear@1
|
513
|
nuclear@1
|
514 // Get device desc.
|
nuclear@1
|
515 if (!HIDManager->getFullDesc(Device, &DevDesc))
|
nuclear@1
|
516 {
|
nuclear@1
|
517 OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device."));
|
nuclear@1
|
518 return false;
|
nuclear@1
|
519 }
|
nuclear@1
|
520
|
nuclear@1
|
521 return true;
|
nuclear@1
|
522 }
|
nuclear@1
|
523
|
nuclear@1
|
524 void HIDDevice::staticDeviceAddedCallback(void* pContext, io_iterator_t iterator)
|
nuclear@1
|
525 {
|
nuclear@1
|
526 HIDDevice* pDevice = (HIDDevice*) pContext;
|
nuclear@1
|
527 pDevice->deviceAddedCallback(iterator);
|
nuclear@1
|
528 }
|
nuclear@1
|
529
|
nuclear@1
|
530 void HIDDevice::deviceAddedCallback(io_iterator_t iterator)
|
nuclear@1
|
531 {
|
nuclear@1
|
532
|
nuclear@1
|
533 if (Device == NULL)
|
nuclear@1
|
534 {
|
nuclear@1
|
535 if (openDevice())
|
nuclear@1
|
536 {
|
nuclear@1
|
537 LogText("OVR::OSX::HIDDevice - Reopened device : %s", DevDesc.Path.ToCStr());
|
nuclear@1
|
538
|
nuclear@1
|
539 Ptr<DeviceCreateDesc> existingHIDDev = HIDManager->DevManager->FindHIDDevice(DevDesc);
|
nuclear@1
|
540 if (existingHIDDev && existingHIDDev->pDevice)
|
nuclear@1
|
541 {
|
nuclear@1
|
542 HIDManager->DevManager->CallOnDeviceAdded(existingHIDDev);
|
nuclear@1
|
543 }
|
nuclear@1
|
544 }
|
nuclear@1
|
545 }
|
nuclear@1
|
546
|
nuclear@1
|
547 // Reset callback.
|
nuclear@1
|
548 while (IOIteratorNext(iterator))
|
nuclear@1
|
549 ;
|
nuclear@1
|
550 }
|
nuclear@1
|
551
|
nuclear@1
|
552 bool HIDDevice::openDevice()
|
nuclear@1
|
553 {
|
nuclear@1
|
554
|
nuclear@1
|
555 // Have to iterate through devices again to generate paths.
|
nuclear@1
|
556 CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager->HIDManager);
|
nuclear@1
|
557 CFIndex deviceCount = CFSetGetCount(deviceSet);
|
nuclear@1
|
558
|
nuclear@1
|
559 // Allocate a block of memory and read the set into it.
|
nuclear@1
|
560 IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount);
|
nuclear@1
|
561 CFSetGetValues(deviceSet, (const void **) devices);
|
nuclear@1
|
562
|
nuclear@1
|
563
|
nuclear@1
|
564 // Iterate over devices.
|
nuclear@1
|
565 IOHIDDeviceRef device = NULL;
|
nuclear@1
|
566
|
nuclear@1
|
567 for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
|
nuclear@1
|
568 {
|
nuclear@1
|
569 IOHIDDeviceRef tmpDevice = devices[deviceIndex];
|
nuclear@1
|
570
|
nuclear@1
|
571 if (!tmpDevice)
|
nuclear@1
|
572 {
|
nuclear@1
|
573 continue;
|
nuclear@1
|
574 }
|
nuclear@1
|
575
|
nuclear@1
|
576 String path;
|
nuclear@1
|
577 if (!HIDManager->getPath(tmpDevice, &path))
|
nuclear@1
|
578 {
|
nuclear@1
|
579 continue;
|
nuclear@1
|
580 }
|
nuclear@1
|
581
|
nuclear@1
|
582 if (path == DevDesc.Path)
|
nuclear@1
|
583 {
|
nuclear@1
|
584 device = tmpDevice;
|
nuclear@1
|
585 break;
|
nuclear@1
|
586 }
|
nuclear@1
|
587 }
|
nuclear@1
|
588
|
nuclear@1
|
589
|
nuclear@1
|
590 OVR_FREE(devices);
|
nuclear@1
|
591
|
nuclear@1
|
592 if (!device)
|
nuclear@1
|
593 {
|
nuclear@1
|
594 CFRelease(deviceSet);
|
nuclear@1
|
595 return false;
|
nuclear@1
|
596 }
|
nuclear@1
|
597
|
nuclear@1
|
598 // Attempt to open device.
|
nuclear@1
|
599 if (IOHIDDeviceOpen(device, kIOHIDOptionsTypeSeizeDevice)
|
nuclear@1
|
600 != kIOReturnSuccess)
|
nuclear@1
|
601 {
|
nuclear@1
|
602 CFRelease(deviceSet);
|
nuclear@1
|
603 return false;
|
nuclear@1
|
604 }
|
nuclear@1
|
605
|
nuclear@1
|
606 // Retain the device before we release the set.
|
nuclear@1
|
607 CFRetain(device);
|
nuclear@1
|
608 CFRelease(deviceSet);
|
nuclear@1
|
609
|
nuclear@1
|
610
|
nuclear@1
|
611 Device = device;
|
nuclear@1
|
612
|
nuclear@1
|
613
|
nuclear@1
|
614 if (!initInfo())
|
nuclear@1
|
615 {
|
nuclear@1
|
616 IOHIDDeviceClose(Device, kIOHIDOptionsTypeSeizeDevice);
|
nuclear@1
|
617 CFRelease(Device);
|
nuclear@1
|
618 Device = NULL;
|
nuclear@1
|
619 return false;
|
nuclear@1
|
620 }
|
nuclear@1
|
621
|
nuclear@1
|
622
|
nuclear@1
|
623 // Setup the Run Loop and callbacks.
|
nuclear@1
|
624 IOHIDDeviceScheduleWithRunLoop(Device,
|
nuclear@1
|
625 HIDManager->getRunLoop(),
|
nuclear@1
|
626 kCFRunLoopDefaultMode);
|
nuclear@1
|
627
|
nuclear@1
|
628 IOHIDDeviceRegisterInputReportCallback(Device,
|
nuclear@1
|
629 ReadBuffer,
|
nuclear@1
|
630 ReadBufferSize,
|
nuclear@1
|
631 staticHIDReportCallback,
|
nuclear@1
|
632 this);
|
nuclear@1
|
633
|
nuclear@1
|
634 IOHIDDeviceRegisterRemovalCallback(Device,
|
nuclear@1
|
635 staticDeviceRemovedCallback,
|
nuclear@1
|
636 this);
|
nuclear@1
|
637
|
nuclear@1
|
638 return true;
|
nuclear@1
|
639 }
|
nuclear@1
|
640
|
nuclear@1
|
641 void HIDDevice::HIDShutdown()
|
nuclear@1
|
642 {
|
nuclear@1
|
643
|
nuclear@1
|
644 HIDManager->DevManager->pThread->RemoveTicksNotifier(this);
|
nuclear@1
|
645
|
nuclear@1
|
646 if (Device != NULL) // Device may already have been closed if unplugged.
|
nuclear@1
|
647 {
|
nuclear@1
|
648 closeDevice(false);
|
nuclear@1
|
649 }
|
nuclear@1
|
650
|
nuclear@1
|
651 IOObjectRelease(RepluggedNotification);
|
nuclear@1
|
652 if (RepluggedNotificationPort)
|
nuclear@1
|
653 IONotificationPortDestroy(RepluggedNotificationPort);
|
nuclear@1
|
654
|
nuclear@1
|
655 LogText("OVR::OSX::HIDDevice - HIDShutdown '%s'\n", DevDesc.Path.ToCStr());
|
nuclear@1
|
656 }
|
nuclear@1
|
657
|
nuclear@1
|
658 bool HIDDevice::setupDevicePluggedInNotification()
|
nuclear@1
|
659 {
|
nuclear@1
|
660
|
nuclear@1
|
661 // Setup notification when devices are plugged in.
|
nuclear@1
|
662 RepluggedNotificationPort = IONotificationPortCreate(kIOMasterPortDefault);
|
nuclear@1
|
663
|
nuclear@1
|
664 CFRunLoopSourceRef notificationRunLoopSource =
|
nuclear@1
|
665 IONotificationPortGetRunLoopSource(RepluggedNotificationPort);
|
nuclear@1
|
666
|
nuclear@1
|
667 CFRunLoopAddSource(HIDManager->getRunLoop(),
|
nuclear@1
|
668 notificationRunLoopSource,
|
nuclear@1
|
669 kCFRunLoopDefaultMode);
|
nuclear@1
|
670
|
nuclear@1
|
671 CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
|
nuclear@1
|
672
|
nuclear@1
|
673 // Have to specify vendorId and productId. Doesn't seem to accept additional
|
nuclear@1
|
674 // things like serial number.
|
nuclear@1
|
675 SInt32 vendorId = DevDesc.VendorId;
|
nuclear@1
|
676 CFNumberRef numberRef = CFNumberCreate(kCFAllocatorDefault,
|
nuclear@1
|
677 kCFNumberSInt32Type,
|
nuclear@1
|
678 &vendorId);
|
nuclear@1
|
679 CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef);
|
nuclear@1
|
680 CFRelease(numberRef);
|
nuclear@1
|
681
|
nuclear@1
|
682 SInt32 deviceProductId = DevDesc.ProductId;
|
nuclear@1
|
683 numberRef = CFNumberCreate(kCFAllocatorDefault,
|
nuclear@1
|
684 kCFNumberSInt32Type,
|
nuclear@1
|
685 &deviceProductId);
|
nuclear@1
|
686 CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef);
|
nuclear@1
|
687 CFRelease(numberRef);
|
nuclear@1
|
688
|
nuclear@1
|
689 kern_return_t result =
|
nuclear@1
|
690 IOServiceAddMatchingNotification(RepluggedNotificationPort,
|
nuclear@1
|
691 kIOMatchedNotification,
|
nuclear@1
|
692 matchingDict,
|
nuclear@1
|
693 staticDeviceAddedCallback,
|
nuclear@1
|
694 this,
|
nuclear@1
|
695 &RepluggedNotification);
|
nuclear@1
|
696
|
nuclear@1
|
697 if (result != KERN_SUCCESS)
|
nuclear@1
|
698 {
|
nuclear@1
|
699 CFRelease(RepluggedNotificationPort);
|
nuclear@1
|
700 RepluggedNotificationPort = 0;
|
nuclear@1
|
701 return false;
|
nuclear@1
|
702 }
|
nuclear@1
|
703
|
nuclear@1
|
704 // Iterate through to arm.
|
nuclear@1
|
705 while (IOIteratorNext(RepluggedNotification))
|
nuclear@1
|
706 {
|
nuclear@1
|
707 }
|
nuclear@1
|
708
|
nuclear@1
|
709 return true;
|
nuclear@1
|
710 }
|
nuclear@1
|
711
|
nuclear@1
|
712 void HIDDevice::closeDevice(bool wasUnplugged)
|
nuclear@1
|
713 {
|
nuclear@1
|
714 OVR_ASSERT(Device != NULL);
|
nuclear@1
|
715
|
nuclear@1
|
716 if (!wasUnplugged)
|
nuclear@1
|
717 {
|
nuclear@1
|
718 // Clear the registered callbacks.
|
nuclear@1
|
719 IOHIDDeviceRegisterInputReportCallback(Device,
|
nuclear@1
|
720 ReadBuffer,
|
nuclear@1
|
721 InputReportBufferLength,
|
nuclear@1
|
722 NULL,
|
nuclear@1
|
723 this);
|
nuclear@1
|
724
|
nuclear@1
|
725 IOHIDDeviceRegisterRemovalCallback(Device, NULL, this);
|
nuclear@1
|
726
|
nuclear@1
|
727 IOHIDDeviceUnscheduleFromRunLoop(Device,
|
nuclear@1
|
728 HIDManager->getRunLoop(),
|
nuclear@1
|
729 kCFRunLoopDefaultMode);
|
nuclear@1
|
730 IOHIDDeviceClose(Device, kIOHIDOptionsTypeNone);
|
nuclear@1
|
731 }
|
nuclear@1
|
732
|
nuclear@1
|
733 CFRelease(Device);
|
nuclear@1
|
734 Device = NULL;
|
nuclear@1
|
735
|
nuclear@1
|
736 LogText("OVR::OSX::HIDDevice - HID Device Closed '%s'\n", DevDesc.Path.ToCStr());
|
nuclear@1
|
737 }
|
nuclear@1
|
738
|
nuclear@1
|
739 void HIDDevice::staticHIDReportCallback(void* pContext,
|
nuclear@1
|
740 IOReturn result,
|
nuclear@1
|
741 void* pSender,
|
nuclear@1
|
742 IOHIDReportType reportType,
|
nuclear@1
|
743 uint32_t reportId,
|
nuclear@1
|
744 uint8_t* pReport,
|
nuclear@1
|
745 CFIndex reportLength)
|
nuclear@1
|
746 {
|
nuclear@1
|
747 HIDDevice* pDevice = (HIDDevice*) pContext;
|
nuclear@1
|
748 return pDevice->hidReportCallback(pReport, (UInt32)reportLength);
|
nuclear@1
|
749 }
|
nuclear@1
|
750
|
nuclear@1
|
751 void HIDDevice::hidReportCallback(UByte* pData, UInt32 length)
|
nuclear@1
|
752 {
|
nuclear@1
|
753
|
nuclear@1
|
754 // We got data.
|
nuclear@1
|
755 if (Handler)
|
nuclear@1
|
756 {
|
nuclear@1
|
757 Handler->OnInputReport(pData, length);
|
nuclear@1
|
758 }
|
nuclear@1
|
759 }
|
nuclear@1
|
760
|
nuclear@1
|
761 void HIDDevice::staticDeviceRemovedCallback(void* pContext, IOReturn result, void* pSender)
|
nuclear@1
|
762 {
|
nuclear@1
|
763 HIDDevice* pDevice = (HIDDevice*) pContext;
|
nuclear@1
|
764 pDevice->deviceRemovedCallback();
|
nuclear@1
|
765 }
|
nuclear@1
|
766
|
nuclear@1
|
767 void HIDDevice::deviceRemovedCallback()
|
nuclear@1
|
768 {
|
nuclear@1
|
769 Ptr<HIDDevice> _this(this); // prevent from release
|
nuclear@1
|
770
|
nuclear@1
|
771 Ptr<DeviceCreateDesc> existingHIDDev = HIDManager->DevManager->FindHIDDevice(DevDesc);
|
nuclear@1
|
772 if (existingHIDDev && existingHIDDev->pDevice)
|
nuclear@1
|
773 {
|
nuclear@1
|
774 HIDManager->DevManager->CallOnDeviceRemoved(existingHIDDev);
|
nuclear@1
|
775 }
|
nuclear@1
|
776 closeDevice(true);
|
nuclear@1
|
777 }
|
nuclear@1
|
778
|
nuclear@1
|
779 CFStringRef HIDDevice::generateRunLoopModeString(IOHIDDeviceRef device)
|
nuclear@1
|
780 {
|
nuclear@1
|
781 const UInt32 safeBuffSize = 256;
|
nuclear@1
|
782 char nameBuff[safeBuffSize];
|
nuclear@1
|
783 OVR_sprintf(nameBuff, safeBuffSize, "%016lX", device);
|
nuclear@1
|
784
|
nuclear@1
|
785 return CFStringCreateWithCString(NULL, nameBuff, kCFStringEncodingASCII);
|
nuclear@1
|
786 }
|
nuclear@1
|
787
|
nuclear@1
|
788 bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length)
|
nuclear@1
|
789 {
|
nuclear@1
|
790
|
nuclear@1
|
791 if (!Device)
|
nuclear@1
|
792 return false;
|
nuclear@1
|
793
|
nuclear@1
|
794 UByte reportID = data[0];
|
nuclear@1
|
795
|
nuclear@1
|
796 if (reportID == 0)
|
nuclear@1
|
797 {
|
nuclear@1
|
798 // Not using reports so remove from data packet.
|
nuclear@1
|
799 data++;
|
nuclear@1
|
800 length--;
|
nuclear@1
|
801 }
|
nuclear@1
|
802
|
nuclear@1
|
803 IOReturn result = IOHIDDeviceSetReport( Device,
|
nuclear@1
|
804 kIOHIDReportTypeFeature,
|
nuclear@1
|
805 reportID,
|
nuclear@1
|
806 data,
|
nuclear@1
|
807 length);
|
nuclear@1
|
808
|
nuclear@1
|
809 return (result == kIOReturnSuccess);
|
nuclear@1
|
810 }
|
nuclear@1
|
811
|
nuclear@1
|
812 bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length)
|
nuclear@1
|
813 {
|
nuclear@1
|
814 if (!Device)
|
nuclear@1
|
815 return false;
|
nuclear@1
|
816
|
nuclear@1
|
817 CFIndex bufferLength = length;
|
nuclear@1
|
818
|
nuclear@1
|
819 // Report id is in first byte of the buffer.
|
nuclear@1
|
820 IOReturn result = IOHIDDeviceGetReport(Device, kIOHIDReportTypeFeature, data[0], data, &bufferLength);
|
nuclear@1
|
821
|
nuclear@1
|
822 return (result == kIOReturnSuccess);
|
nuclear@1
|
823 }
|
nuclear@1
|
824
|
nuclear@1
|
825 UInt64 HIDDevice::OnTicks(UInt64 ticksMks)
|
nuclear@1
|
826 {
|
nuclear@1
|
827
|
nuclear@1
|
828 if (Handler)
|
nuclear@1
|
829 {
|
nuclear@1
|
830 return Handler->OnTicks(ticksMks);
|
nuclear@1
|
831 }
|
nuclear@1
|
832
|
nuclear@1
|
833 return DeviceManagerThread::Notifier::OnTicks(ticksMks);
|
nuclear@1
|
834 }
|
nuclear@1
|
835
|
nuclear@1
|
836 HIDDeviceManager* HIDDeviceManager::CreateInternal(OSX::DeviceManager* devManager)
|
nuclear@1
|
837 {
|
nuclear@1
|
838
|
nuclear@1
|
839 if (!System::IsInitialized())
|
nuclear@1
|
840 {
|
nuclear@1
|
841 // Use custom message, since Log is not yet installed.
|
nuclear@1
|
842 OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
|
nuclear@1
|
843 LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
|
nuclear@1
|
844 return 0;
|
nuclear@1
|
845 }
|
nuclear@1
|
846
|
nuclear@1
|
847 Ptr<OSX::HIDDeviceManager> manager = *new OSX::HIDDeviceManager(devManager);
|
nuclear@1
|
848
|
nuclear@1
|
849 if (manager)
|
nuclear@1
|
850 {
|
nuclear@1
|
851 if (manager->Initialize())
|
nuclear@1
|
852 {
|
nuclear@1
|
853 manager->AddRef();
|
nuclear@1
|
854 }
|
nuclear@1
|
855 else
|
nuclear@1
|
856 {
|
nuclear@1
|
857 manager.Clear();
|
nuclear@1
|
858 }
|
nuclear@1
|
859 }
|
nuclear@1
|
860
|
nuclear@1
|
861 return manager.GetPtr();
|
nuclear@1
|
862 }
|
nuclear@1
|
863
|
nuclear@1
|
864 } // namespace OSX
|
nuclear@1
|
865
|
nuclear@1
|
866 //-------------------------------------------------------------------------------------
|
nuclear@1
|
867 // ***** Creation
|
nuclear@1
|
868
|
nuclear@1
|
869 // Creates a new HIDDeviceManager and initializes OVR.
|
nuclear@1
|
870 HIDDeviceManager* HIDDeviceManager::Create()
|
nuclear@1
|
871 {
|
nuclear@1
|
872 OVR_ASSERT_LOG(false, ("Standalone mode not implemented yet."));
|
nuclear@1
|
873
|
nuclear@1
|
874 if (!System::IsInitialized())
|
nuclear@1
|
875 {
|
nuclear@1
|
876 // Use custom message, since Log is not yet installed.
|
nuclear@1
|
877 OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
|
nuclear@1
|
878 LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
|
nuclear@1
|
879 return 0;
|
nuclear@1
|
880 }
|
nuclear@1
|
881
|
nuclear@1
|
882 Ptr<OSX::HIDDeviceManager> manager = *new OSX::HIDDeviceManager(NULL);
|
nuclear@1
|
883
|
nuclear@1
|
884 if (manager)
|
nuclear@1
|
885 {
|
nuclear@1
|
886 if (manager->Initialize())
|
nuclear@1
|
887 {
|
nuclear@1
|
888 manager->AddRef();
|
nuclear@1
|
889 }
|
nuclear@1
|
890 else
|
nuclear@1
|
891 {
|
nuclear@1
|
892 manager.Clear();
|
nuclear@1
|
893 }
|
nuclear@1
|
894 }
|
nuclear@1
|
895
|
nuclear@1
|
896 return manager.GetPtr();
|
nuclear@1
|
897 }
|
nuclear@1
|
898
|
nuclear@1
|
899 } // namespace OVR
|