00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "OVR_Win32_HIDDevice.h"
00017 #include "OVR_Win32_DeviceManager.h"
00018
00019 #include "Kernel/OVR_System.h"
00020 #include "Kernel/OVR_Log.h"
00021
00022 namespace OVR { namespace Win32 {
00023
00024
00025
00026
00027 class HIDDevicePathWrapper
00028 {
00029 SP_INTERFACE_DEVICE_DETAIL_DATA_A* pData;
00030 public:
00031 HIDDevicePathWrapper() : pData(0) { }
00032 ~HIDDevicePathWrapper() { if (pData) OVR_FREE(pData); }
00033
00034 const char* GetPath() const { return pData ? pData->DevicePath : 0; }
00035
00036 bool InitPathFromInterfaceData(HDEVINFO hdevInfoSet, SP_DEVICE_INTERFACE_DATA* pidata);
00037 };
00038
00039 bool HIDDevicePathWrapper::InitPathFromInterfaceData(HDEVINFO hdevInfoSet, SP_DEVICE_INTERFACE_DATA* pidata)
00040 {
00041 DWORD detailSize = 0;
00042
00043
00044 SetupDiGetDeviceInterfaceDetailA(hdevInfoSet, pidata, NULL, 0, &detailSize, NULL);
00045 if (!detailSize ||
00046 ((pData = (SP_INTERFACE_DEVICE_DETAIL_DATA_A*)OVR_ALLOC(detailSize)) == 0))
00047 return false;
00048 pData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA_A);
00049
00050 if (!SetupDiGetDeviceInterfaceDetailA(hdevInfoSet, pidata, pData, detailSize, NULL, NULL))
00051 return false;
00052 return true;
00053 }
00054
00055
00056
00057
00058
00059 HIDDeviceManager::HIDDeviceManager(DeviceManager* manager)
00060 : Manager(manager)
00061 {
00062 hHidLib = ::LoadLibraryA("hid.dll");
00063 OVR_ASSERT_LOG(hHidLib, ("Couldn't load Win32 'hid.dll'."));
00064
00065 OVR_RESOLVE_HIDFUNC(HidD_GetHidGuid);
00066 OVR_RESOLVE_HIDFUNC(HidD_SetNumInputBuffers);
00067 OVR_RESOLVE_HIDFUNC(HidD_GetFeature);
00068 OVR_RESOLVE_HIDFUNC(HidD_SetFeature);
00069 OVR_RESOLVE_HIDFUNC(HidD_GetAttributes);
00070 OVR_RESOLVE_HIDFUNC(HidD_GetManufacturerString);
00071 OVR_RESOLVE_HIDFUNC(HidD_GetProductString);
00072 OVR_RESOLVE_HIDFUNC(HidD_GetSerialNumberString);
00073 OVR_RESOLVE_HIDFUNC(HidD_GetPreparsedData);
00074 OVR_RESOLVE_HIDFUNC(HidD_FreePreparsedData);
00075 OVR_RESOLVE_HIDFUNC(HidP_GetCaps);
00076
00077 if (HidD_GetHidGuid)
00078 HidD_GetHidGuid(&HidGuid);
00079 }
00080
00081 HIDDeviceManager::~HIDDeviceManager()
00082 {
00083 ::FreeLibrary(hHidLib);
00084 }
00085
00086 bool HIDDeviceManager::Initialize()
00087 {
00088 return true;
00089 }
00090
00091 void HIDDeviceManager::Shutdown()
00092 {
00093 LogText("OVR::Win32::HIDDeviceManager - shutting down.\n");
00094 }
00095
00096 bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor)
00097 {
00098 HDEVINFO hdevInfoSet;
00099 SP_DEVICE_INTERFACE_DATA interfaceData;
00100 interfaceData.cbSize = sizeof(interfaceData);
00101
00102
00103 hdevInfoSet = SetupDiGetClassDevsA(&HidGuid, NULL, NULL, DIGCF_INTERFACEDEVICE | DIGCF_PRESENT);
00104 if (hdevInfoSet == INVALID_HANDLE_VALUE)
00105 return false;
00106
00107 for(int deviceIndex = 0;
00108 SetupDiEnumDeviceInterfaces(hdevInfoSet, NULL, &HidGuid, deviceIndex, &interfaceData);
00109 deviceIndex++)
00110 {
00111
00112
00113 HIDDevicePathWrapper pathWrapper;
00114 if (!pathWrapper.InitPathFromInterfaceData(hdevInfoSet, &interfaceData))
00115 continue;
00116
00117
00118 Ptr<DeviceCreateDesc> existingDevice = Manager->FindDevice(pathWrapper.GetPath());
00119
00120
00121 if (existingDevice && existingDevice->pDevice)
00122 {
00123 existingDevice->Enumerated = true;
00124 continue;
00125 }
00126
00127
00128 HANDLE hidDev = CreateHIDFile(pathWrapper.GetPath(), false);
00129 if (hidDev == INVALID_HANDLE_VALUE)
00130 continue;
00131
00132 HIDDeviceDesc devDesc;
00133 devDesc.Path = pathWrapper.GetPath();
00134 if (initVendorProductVersion(hidDev, &devDesc) &&
00135 enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId) &&
00136 initUsage(hidDev, &devDesc))
00137 {
00138 initStrings(hidDev, &devDesc);
00139
00140
00141 Win32::HIDDevice device(this, hidDev);
00142 enumVisitor->Visit(device, devDesc);
00143 }
00144
00145 ::CloseHandle(hidDev);
00146 }
00147
00148 SetupDiDestroyDeviceInfoList(hdevInfoSet);
00149 return true;
00150 }
00151
00152 bool HIDDeviceManager::GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const
00153 {
00154
00155 HANDLE hidDev = CreateHIDFile(path, false);
00156 if (hidDev == INVALID_HANDLE_VALUE)
00157 return false;
00158
00159 pdevDesc->Path = path;
00160 getFullDesc(hidDev, pdevDesc);
00161
00162 ::CloseHandle(hidDev);
00163 return true;
00164 }
00165
00166 OVR::HIDDevice* HIDDeviceManager::Open(const String& path)
00167 {
00168
00169 Ptr<Win32::HIDDevice> device = *new Win32::HIDDevice(this);
00170
00171 if (device->HIDInitialize(path))
00172 {
00173 device->AddRef();
00174 return device;
00175 }
00176
00177 return NULL;
00178 }
00179
00180 bool HIDDeviceManager::getFullDesc(HANDLE hidDev, HIDDeviceDesc* desc) const
00181 {
00182
00183 if (!initVendorProductVersion(hidDev, desc))
00184 {
00185 return false;
00186 }
00187
00188 if (!initUsage(hidDev, desc))
00189 {
00190 return false;
00191 }
00192
00193 initStrings(hidDev, desc);
00194
00195 return true;
00196 }
00197
00198 bool HIDDeviceManager::initVendorProductVersion(HANDLE hidDev, HIDDeviceDesc* desc) const
00199 {
00200 HIDD_ATTRIBUTES attr;
00201 attr.Size = sizeof(attr);
00202 if (!HidD_GetAttributes(hidDev, &attr))
00203 return false;
00204 desc->VendorId = attr.VendorID;
00205 desc->ProductId = attr.ProductID;
00206 desc->VersionNumber = attr.VersionNumber;
00207 return true;
00208 }
00209
00210 bool HIDDeviceManager::initUsage(HANDLE hidDev, HIDDeviceDesc* desc) const
00211 {
00212 bool result = false;
00213 HIDP_CAPS caps;
00214 HIDP_PREPARSED_DATA* preparsedData = 0;
00215
00216 if (!HidD_GetPreparsedData(hidDev, &preparsedData))
00217 return false;
00218
00219 if (HidP_GetCaps(preparsedData, &caps) == HIDP_STATUS_SUCCESS)
00220 {
00221 desc->Usage = caps.Usage;
00222 desc->UsagePage = caps.UsagePage;
00223 result = true;
00224 }
00225 HidD_FreePreparsedData(preparsedData);
00226 return result;
00227 }
00228
00229 void HIDDeviceManager::initStrings(HANDLE hidDev, HIDDeviceDesc* desc) const
00230 {
00231
00232 wchar_t strBuffer[196];
00233
00234
00235
00236 strBuffer[0] = 0;
00237 HidD_GetManufacturerString(hidDev, strBuffer, sizeof(strBuffer));
00238 desc->Manufacturer = strBuffer;
00239
00240 strBuffer[0] = 0;
00241 HidD_GetProductString(hidDev, strBuffer, sizeof(strBuffer));
00242 desc->Product = strBuffer;
00243
00244 strBuffer[0] = 0;
00245 HidD_GetSerialNumberString(hidDev, strBuffer, sizeof(strBuffer));
00246 desc->SerialNumber = strBuffer;
00247 }
00248
00249
00250
00251
00252 HIDDevice::HIDDevice(HIDDeviceManager* manager)
00253 : HIDManager(manager), inMinimalMode(false), Device(0), ReadRequested(false)
00254 {
00255 memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
00256 }
00257
00258
00259
00260 HIDDevice::HIDDevice(HIDDeviceManager* manager, HANDLE device)
00261 : HIDManager(manager), inMinimalMode(true), Device(device), ReadRequested(true)
00262 {
00263 memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
00264 }
00265
00266 HIDDevice::~HIDDevice()
00267 {
00268 if (!inMinimalMode)
00269 {
00270 HIDShutdown();
00271 }
00272 }
00273
00274 bool HIDDevice::HIDInitialize(const String& path)
00275 {
00276
00277 DevDesc.Path = path;
00278
00279 if (!openDevice())
00280 {
00281 LogText("OVR::Win32::HIDDevice - Failed to open HIDDevice: ", path);
00282 return false;
00283 }
00284
00285
00286 HIDManager->Manager->pThread->AddTicksNotifier(this);
00287 HIDManager->Manager->pThread->AddMessageNotifier(this);
00288
00289 LogText("OVR::Win32::HIDDevice - Opened '%s'\n"
00290 " Manufacturer:'%s' Product:'%s' Serial#:'%s'\n",
00291 DevDesc.Path.ToCStr(),
00292 DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(),
00293 DevDesc.SerialNumber.ToCStr());
00294
00295 return true;
00296 }
00297
00298 bool HIDDevice::initInfo()
00299 {
00300
00301 OVR_ASSERT(Device);
00302
00303
00304 HIDP_PREPARSED_DATA* preparsedData = 0;
00305 if (!HIDManager->HidD_GetPreparsedData(Device, &preparsedData))
00306 {
00307 return false;
00308 }
00309
00310 HIDP_CAPS caps;
00311 if (HIDManager->HidP_GetCaps(preparsedData, &caps) != HIDP_STATUS_SUCCESS)
00312 {
00313 HIDManager->HidD_FreePreparsedData(preparsedData);
00314 return false;
00315 }
00316
00317 InputReportBufferLength = caps.InputReportByteLength;
00318 OutputReportBufferLength = caps.OutputReportByteLength;
00319 FeatureReportBufferLength= caps.FeatureReportByteLength;
00320 HIDManager->HidD_FreePreparsedData(preparsedData);
00321
00322 if (ReadBufferSize < InputReportBufferLength)
00323 {
00324 OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
00325 return false;
00326 }
00327
00328
00329 if (!HIDManager->getFullDesc(Device, &DevDesc))
00330 {
00331 OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device."));
00332 return false;
00333 }
00334
00335 return true;
00336 }
00337
00338 bool HIDDevice::openDevice()
00339 {
00340 memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
00341
00342 Device = HIDManager->CreateHIDFile(DevDesc.Path.ToCStr());
00343 if (Device == INVALID_HANDLE_VALUE)
00344 {
00345 OVR_DEBUG_LOG(("Failed 'CreateHIDFile' while opening device, error = 0x%X.",
00346 ::GetLastError()));
00347 Device = 0;
00348 return false;
00349 }
00350
00351 if (!HIDManager->HidD_SetNumInputBuffers(Device, 128))
00352 {
00353 OVR_ASSERT_LOG(false, ("Failed 'HidD_SetNumInputBuffers' while initializing device."));
00354 ::CloseHandle(Device);
00355 Device = 0;
00356 return false;
00357 }
00358
00359
00360
00361 ReadOverlapped.hEvent = ::CreateEvent(0, TRUE, FALSE, 0);
00362
00363 if (!ReadOverlapped.hEvent)
00364 {
00365 OVR_ASSERT_LOG(false, ("Failed to create event."));
00366 ::CloseHandle(Device);
00367 Device = 0;
00368 return false;
00369 }
00370
00371 if (!initInfo())
00372 {
00373 OVR_ASSERT_LOG(false, ("Failed to get HIDDevice info."));
00374
00375 ::CloseHandle(ReadOverlapped.hEvent);
00376 memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
00377
00378 ::CloseHandle(Device);
00379 Device = 0;
00380 return false;
00381 }
00382
00383 if (!initializeRead())
00384 {
00385 OVR_ASSERT_LOG(false, ("Failed to get intialize read for HIDDevice."));
00386
00387 ::CloseHandle(ReadOverlapped.hEvent);
00388 memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
00389
00390 ::CloseHandle(Device);
00391 Device = 0;
00392 return false;
00393 }
00394
00395 return true;
00396 }
00397
00398 void HIDDevice::HIDShutdown()
00399 {
00400
00401 HIDManager->Manager->pThread->RemoveTicksNotifier(this);
00402 HIDManager->Manager->pThread->RemoveMessageNotifier(this);
00403
00404 closeDevice();
00405 LogText("OVR::Win32::HIDDevice - Closed '%s'\n", DevDesc.Path.ToCStr());
00406 }
00407
00408 bool HIDDevice::initializeRead()
00409 {
00410
00411 if (!ReadRequested)
00412 {
00413 HIDManager->Manager->pThread->AddOverlappedEvent(this, ReadOverlapped.hEvent);
00414 ReadRequested = true;
00415 }
00416
00417
00418 while(::ReadFile(Device, ReadBuffer, InputReportBufferLength, 0, &ReadOverlapped))
00419 {
00420 processReadResult();
00421 }
00422
00423 if (GetLastError() != ERROR_IO_PENDING)
00424 {
00425
00426 closeDeviceOnIOError();
00427 return false;
00428 }
00429
00430 return true;
00431 }
00432
00433 bool HIDDevice::processReadResult()
00434 {
00435
00436 OVR_ASSERT(ReadRequested);
00437
00438 DWORD bytesRead = 0;
00439
00440 if (GetOverlappedResult(Device, &ReadOverlapped, &bytesRead, FALSE))
00441 {
00442
00443 if (Handler)
00444 {
00445 Handler->OnInputReport(ReadBuffer, bytesRead);
00446 }
00447
00448
00449
00450 ReadOverlapped.Pointer = 0;
00451 ReadOverlapped.Internal = 0;
00452 ReadOverlapped.InternalHigh = 0;
00453 return true;
00454 }
00455 else
00456 {
00457 if (GetLastError() != ERROR_IO_PENDING)
00458 {
00459 closeDeviceOnIOError();
00460 return false;
00461 }
00462 }
00463
00464 return false;
00465 }
00466
00467 void HIDDevice::closeDevice()
00468 {
00469 if (ReadRequested)
00470 {
00471 HIDManager->Manager->pThread->RemoveOverlappedEvent(this, ReadOverlapped.hEvent);
00472 ReadRequested = false;
00473
00474 ::CancelIo(Device);
00475 }
00476
00477 ::CloseHandle(ReadOverlapped.hEvent);
00478 memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
00479
00480 ::CloseHandle(Device);
00481 Device = 0;
00482 }
00483
00484 void HIDDevice::closeDeviceOnIOError()
00485 {
00486 LogText("OVR::Win32::HIDDevice - Lost connection to '%s'\n", DevDesc.Path.ToCStr());
00487 closeDevice();
00488 }
00489
00490 bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length)
00491 {
00492 if (!ReadRequested)
00493 return false;
00494
00495 return HIDManager->HidD_SetFeature(Device, data, (ULONG) length) != FALSE;
00496 }
00497
00498 bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length)
00499 {
00500 if (!ReadRequested)
00501 return false;
00502
00503 return HIDManager->HidD_GetFeature(Device, data, (ULONG) length) != FALSE;
00504 }
00505
00506 void HIDDevice::OnOverlappedEvent(HANDLE hevent)
00507 {
00508 OVR_UNUSED(hevent);
00509 OVR_ASSERT(hevent == ReadOverlapped.hEvent);
00510
00511 if (processReadResult())
00512 {
00513
00514 initializeRead();
00515 }
00516 }
00517
00518 UInt64 HIDDevice::OnTicks(UInt64 ticksMks)
00519 {
00520 if (Handler)
00521 {
00522 return Handler->OnTicks(ticksMks);
00523 }
00524
00525 return DeviceManagerThread::Notifier::OnTicks(ticksMks);
00526 }
00527
00528 bool HIDDevice::OnDeviceMessage(DeviceMessageType messageType,
00529 const String& devicePath,
00530 bool* error)
00531 {
00532
00533
00534 if (DevDesc.Path.CompareNoCase(devicePath) != 0)
00535 {
00536 return false;
00537 }
00538
00539 if (messageType == DeviceMessage_DeviceAdded && !Device)
00540 {
00541
00542 if (!openDevice())
00543 {
00544 LogError("OVR::Win32::HIDDevice - Failed to reopen a device '%s' that was re-added.\n", devicePath.ToCStr());
00545 *error = true;
00546 return true;
00547 }
00548
00549 LogText("OVR::Win32::HIDDevice - Reopened device '%s'\n", devicePath.ToCStr());
00550 }
00551
00552 HIDHandler::HIDDeviceMessageType handlerMessageType = HIDHandler::HIDDeviceMessage_DeviceAdded;
00553 if (messageType == DeviceMessage_DeviceAdded)
00554 {
00555 }
00556 else if (messageType == DeviceMessage_DeviceRemoved)
00557 {
00558 handlerMessageType = HIDHandler::HIDDeviceMessage_DeviceRemoved;
00559 }
00560 else
00561 {
00562 OVR_ASSERT(0);
00563 }
00564
00565 if (Handler)
00566 {
00567 Handler->OnDeviceMessage(handlerMessageType);
00568 }
00569
00570 *error = false;
00571 return true;
00572 }
00573
00574 HIDDeviceManager* HIDDeviceManager::CreateInternal(Win32::DeviceManager* devManager)
00575 {
00576
00577 if (!System::IsInitialized())
00578 {
00579
00580 OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
00581 LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
00582 return 0;
00583 }
00584
00585 Ptr<Win32::HIDDeviceManager> manager = *new Win32::HIDDeviceManager(devManager);
00586
00587 if (manager)
00588 {
00589 if (manager->Initialize())
00590 {
00591 manager->AddRef();
00592 }
00593 else
00594 {
00595 manager.Clear();
00596 }
00597 }
00598
00599 return manager.GetPtr();
00600 }
00601
00602 }
00603
00604
00605
00606
00607
00608 HIDDeviceManager* HIDDeviceManager::Create()
00609 {
00610 OVR_ASSERT_LOG(false, ("Standalone mode not implemented yet."));
00611
00612 if (!System::IsInitialized())
00613 {
00614
00615 OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
00616 LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
00617 return 0;
00618 }
00619
00620 Ptr<Win32::HIDDeviceManager> manager = *new Win32::HIDDeviceManager(NULL);
00621
00622 if (manager)
00623 {
00624 if (manager->Initialize())
00625 {
00626 manager->AddRef();
00627 }
00628 else
00629 {
00630 manager.Clear();
00631 }
00632 }
00633
00634 return manager.GetPtr();
00635 }
00636
00637 }