nuclear@1: /************************************************************************************ nuclear@1: nuclear@1: Filename : OVR_Win32_HIDDevice.cpp nuclear@1: Content : Win32 HID device implementation. nuclear@1: Created : February 22, 2013 nuclear@1: Authors : Lee Cooper nuclear@1: nuclear@1: Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. nuclear@1: nuclear@1: Use of this software is subject to the terms of the Oculus license nuclear@1: agreement provided at the time of installation or download, or which nuclear@1: otherwise accompanies this software in either electronic or hard copy form. nuclear@1: nuclear@1: *************************************************************************************/ nuclear@1: nuclear@1: #include "OVR_Win32_HIDDevice.h" nuclear@1: #include "OVR_Win32_DeviceManager.h" nuclear@1: nuclear@1: #include "Kernel/OVR_System.h" nuclear@1: #include "Kernel/OVR_Log.h" nuclear@1: nuclear@1: namespace OVR { namespace Win32 { nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // HIDDevicePathWrapper is a simple class used to extract HID device file path nuclear@1: // through SetupDiGetDeviceInterfaceDetail. We use a class since this is a bit messy. nuclear@1: class HIDDevicePathWrapper nuclear@1: { nuclear@1: SP_INTERFACE_DEVICE_DETAIL_DATA_A* pData; nuclear@1: public: nuclear@1: HIDDevicePathWrapper() : pData(0) { } nuclear@1: ~HIDDevicePathWrapper() { if (pData) OVR_FREE(pData); } nuclear@1: nuclear@1: const char* GetPath() const { return pData ? pData->DevicePath : 0; } nuclear@1: nuclear@1: bool InitPathFromInterfaceData(HDEVINFO hdevInfoSet, SP_DEVICE_INTERFACE_DATA* pidata); nuclear@1: }; nuclear@1: nuclear@1: bool HIDDevicePathWrapper::InitPathFromInterfaceData(HDEVINFO hdevInfoSet, SP_DEVICE_INTERFACE_DATA* pidata) nuclear@1: { nuclear@1: DWORD detailSize = 0; nuclear@1: // SetupDiGetDeviceInterfaceDetailA returns "not enough buffer error code" nuclear@1: // doe size request. Just check valid size. nuclear@1: SetupDiGetDeviceInterfaceDetailA(hdevInfoSet, pidata, NULL, 0, &detailSize, NULL); nuclear@1: if (!detailSize || nuclear@1: ((pData = (SP_INTERFACE_DEVICE_DETAIL_DATA_A*)OVR_ALLOC(detailSize)) == 0)) nuclear@1: return false; nuclear@1: pData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA_A); nuclear@1: nuclear@1: if (!SetupDiGetDeviceInterfaceDetailA(hdevInfoSet, pidata, pData, detailSize, NULL, NULL)) nuclear@1: return false; nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // **** Win32::DeviceManager nuclear@1: nuclear@1: HIDDeviceManager::HIDDeviceManager(DeviceManager* manager) nuclear@1: : Manager(manager) nuclear@1: { nuclear@1: hHidLib = ::LoadLibraryA("hid.dll"); nuclear@1: OVR_ASSERT_LOG(hHidLib, ("Couldn't load Win32 'hid.dll'.")); nuclear@1: nuclear@1: OVR_RESOLVE_HIDFUNC(HidD_GetHidGuid); nuclear@1: OVR_RESOLVE_HIDFUNC(HidD_SetNumInputBuffers); nuclear@1: OVR_RESOLVE_HIDFUNC(HidD_GetFeature); nuclear@1: OVR_RESOLVE_HIDFUNC(HidD_SetFeature); nuclear@1: OVR_RESOLVE_HIDFUNC(HidD_GetAttributes); nuclear@1: OVR_RESOLVE_HIDFUNC(HidD_GetManufacturerString); nuclear@1: OVR_RESOLVE_HIDFUNC(HidD_GetProductString); nuclear@1: OVR_RESOLVE_HIDFUNC(HidD_GetSerialNumberString); nuclear@1: OVR_RESOLVE_HIDFUNC(HidD_GetPreparsedData); nuclear@1: OVR_RESOLVE_HIDFUNC(HidD_FreePreparsedData); nuclear@1: OVR_RESOLVE_HIDFUNC(HidP_GetCaps); nuclear@1: nuclear@1: if (HidD_GetHidGuid) nuclear@1: HidD_GetHidGuid(&HidGuid); nuclear@1: } nuclear@1: nuclear@1: HIDDeviceManager::~HIDDeviceManager() nuclear@1: { nuclear@1: ::FreeLibrary(hHidLib); nuclear@1: } nuclear@1: nuclear@1: bool HIDDeviceManager::Initialize() nuclear@1: { nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: void HIDDeviceManager::Shutdown() nuclear@1: { nuclear@1: LogText("OVR::Win32::HIDDeviceManager - shutting down.\n"); nuclear@1: } nuclear@1: nuclear@1: bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor) nuclear@1: { nuclear@1: HDEVINFO hdevInfoSet; nuclear@1: SP_DEVICE_INTERFACE_DATA interfaceData; nuclear@1: interfaceData.cbSize = sizeof(interfaceData); nuclear@1: nuclear@1: // Get handle to info data set describing all available HIDs. nuclear@1: hdevInfoSet = SetupDiGetClassDevsA(&HidGuid, NULL, NULL, DIGCF_INTERFACEDEVICE | DIGCF_PRESENT); nuclear@1: if (hdevInfoSet == INVALID_HANDLE_VALUE) nuclear@1: return false; nuclear@1: nuclear@1: for(int deviceIndex = 0; nuclear@1: SetupDiEnumDeviceInterfaces(hdevInfoSet, NULL, &HidGuid, deviceIndex, &interfaceData); nuclear@1: deviceIndex++) nuclear@1: { nuclear@1: // For each device, we extract its file path and open it to get attributes, nuclear@1: // such as vendor and product id. If anything goes wrong, we move onto next device. nuclear@1: HIDDevicePathWrapper pathWrapper; nuclear@1: if (!pathWrapper.InitPathFromInterfaceData(hdevInfoSet, &interfaceData)) nuclear@1: continue; nuclear@1: nuclear@1: // Look for the device to check if it is already opened. nuclear@1: Ptr existingDevice = Manager->FindDevice(pathWrapper.GetPath()); nuclear@1: // if device exists and it is opened then most likely the CreateHIDFile nuclear@1: // will fail; therefore, we just set Enumerated to 'true' and continue. nuclear@1: if (existingDevice && existingDevice->pDevice) nuclear@1: { nuclear@1: existingDevice->Enumerated = true; nuclear@1: continue; nuclear@1: } nuclear@1: nuclear@1: // open device in non-exclusive mode for detection... nuclear@1: HANDLE hidDev = CreateHIDFile(pathWrapper.GetPath(), false); nuclear@1: if (hidDev == INVALID_HANDLE_VALUE) nuclear@1: continue; nuclear@1: nuclear@1: HIDDeviceDesc devDesc; nuclear@1: devDesc.Path = pathWrapper.GetPath(); nuclear@1: if (initVendorProductVersion(hidDev, &devDesc) && nuclear@1: enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId) && nuclear@1: initUsage(hidDev, &devDesc)) nuclear@1: { nuclear@1: initStrings(hidDev, &devDesc); nuclear@1: nuclear@1: // Construct minimal device that the visitor callback can get feature reports from. nuclear@1: Win32::HIDDevice device(this, hidDev); nuclear@1: enumVisitor->Visit(device, devDesc); nuclear@1: } nuclear@1: nuclear@1: ::CloseHandle(hidDev); nuclear@1: } nuclear@1: nuclear@1: SetupDiDestroyDeviceInfoList(hdevInfoSet); nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: bool HIDDeviceManager::GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const nuclear@1: { nuclear@1: // open device in non-exclusive mode for detection... nuclear@1: HANDLE hidDev = CreateHIDFile(path, false); nuclear@1: if (hidDev == INVALID_HANDLE_VALUE) nuclear@1: return false; nuclear@1: nuclear@1: pdevDesc->Path = path; nuclear@1: getFullDesc(hidDev, pdevDesc); nuclear@1: nuclear@1: ::CloseHandle(hidDev); nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: OVR::HIDDevice* HIDDeviceManager::Open(const String& path) nuclear@1: { nuclear@1: nuclear@1: Ptr device = *new Win32::HIDDevice(this); nuclear@1: nuclear@1: if (device->HIDInitialize(path)) nuclear@1: { nuclear@1: device->AddRef(); nuclear@1: return device; nuclear@1: } nuclear@1: nuclear@1: return NULL; nuclear@1: } nuclear@1: nuclear@1: bool HIDDeviceManager::getFullDesc(HANDLE hidDev, HIDDeviceDesc* desc) const nuclear@1: { nuclear@1: nuclear@1: if (!initVendorProductVersion(hidDev, desc)) nuclear@1: { nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: if (!initUsage(hidDev, desc)) nuclear@1: { nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: initStrings(hidDev, desc); nuclear@1: nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: bool HIDDeviceManager::initVendorProductVersion(HANDLE hidDev, HIDDeviceDesc* desc) const nuclear@1: { nuclear@1: HIDD_ATTRIBUTES attr; nuclear@1: attr.Size = sizeof(attr); nuclear@1: if (!HidD_GetAttributes(hidDev, &attr)) nuclear@1: return false; nuclear@1: desc->VendorId = attr.VendorID; nuclear@1: desc->ProductId = attr.ProductID; nuclear@1: desc->VersionNumber = attr.VersionNumber; nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: bool HIDDeviceManager::initUsage(HANDLE hidDev, HIDDeviceDesc* desc) const nuclear@1: { nuclear@1: bool result = false; nuclear@1: HIDP_CAPS caps; nuclear@1: HIDP_PREPARSED_DATA* preparsedData = 0; nuclear@1: nuclear@1: if (!HidD_GetPreparsedData(hidDev, &preparsedData)) nuclear@1: return false; nuclear@1: nuclear@1: if (HidP_GetCaps(preparsedData, &caps) == HIDP_STATUS_SUCCESS) nuclear@1: { nuclear@1: desc->Usage = caps.Usage; nuclear@1: desc->UsagePage = caps.UsagePage; nuclear@1: result = true; nuclear@1: } nuclear@1: HidD_FreePreparsedData(preparsedData); nuclear@1: return result; nuclear@1: } nuclear@1: nuclear@1: void HIDDeviceManager::initStrings(HANDLE hidDev, HIDDeviceDesc* desc) const nuclear@1: { nuclear@1: // Documentation mentions 126 as being the max for USB. nuclear@1: wchar_t strBuffer[196]; nuclear@1: nuclear@1: // HidD_Get*String functions return nothing in buffer on failure, nuclear@1: // so it's ok to do this without further error checking. nuclear@1: strBuffer[0] = 0; nuclear@1: HidD_GetManufacturerString(hidDev, strBuffer, sizeof(strBuffer)); nuclear@1: desc->Manufacturer = strBuffer; nuclear@1: nuclear@1: strBuffer[0] = 0; nuclear@1: HidD_GetProductString(hidDev, strBuffer, sizeof(strBuffer)); nuclear@1: desc->Product = strBuffer; nuclear@1: nuclear@1: strBuffer[0] = 0; nuclear@1: HidD_GetSerialNumberString(hidDev, strBuffer, sizeof(strBuffer)); nuclear@1: desc->SerialNumber = strBuffer; nuclear@1: } nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // **** Win32::HIDDevice nuclear@1: nuclear@1: HIDDevice::HIDDevice(HIDDeviceManager* manager) nuclear@1: : HIDManager(manager), inMinimalMode(false), Device(0), ReadRequested(false) nuclear@1: { nuclear@1: memset(&ReadOverlapped, 0, sizeof(OVERLAPPED)); nuclear@1: } nuclear@1: nuclear@1: // This is a minimal constructor used during enumeration for us to pass nuclear@1: // a HIDDevice to the visit function (so that it can query feature reports). nuclear@1: HIDDevice::HIDDevice(HIDDeviceManager* manager, HANDLE device) nuclear@1: : HIDManager(manager), inMinimalMode(true), Device(device), ReadRequested(true) nuclear@1: { nuclear@1: memset(&ReadOverlapped, 0, sizeof(OVERLAPPED)); nuclear@1: } nuclear@1: nuclear@1: HIDDevice::~HIDDevice() nuclear@1: { nuclear@1: if (!inMinimalMode) nuclear@1: { nuclear@1: HIDShutdown(); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: bool HIDDevice::HIDInitialize(const String& path) nuclear@1: { nuclear@1: nuclear@1: DevDesc.Path = path; nuclear@1: nuclear@1: if (!openDevice()) nuclear@1: { nuclear@1: LogText("OVR::Win32::HIDDevice - Failed to open HIDDevice: ", path); nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: nuclear@1: HIDManager->Manager->pThread->AddTicksNotifier(this); nuclear@1: HIDManager->Manager->pThread->AddMessageNotifier(this); nuclear@1: nuclear@1: LogText("OVR::Win32::HIDDevice - Opened '%s'\n" nuclear@1: " Manufacturer:'%s' Product:'%s' Serial#:'%s'\n", nuclear@1: DevDesc.Path.ToCStr(), nuclear@1: DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(), nuclear@1: DevDesc.SerialNumber.ToCStr()); nuclear@1: nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: bool HIDDevice::initInfo() nuclear@1: { nuclear@1: // Device must have been successfully opened. nuclear@1: OVR_ASSERT(Device); nuclear@1: nuclear@1: // Get report lengths. nuclear@1: HIDP_PREPARSED_DATA* preparsedData = 0; nuclear@1: if (!HIDManager->HidD_GetPreparsedData(Device, &preparsedData)) nuclear@1: { nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: HIDP_CAPS caps; nuclear@1: if (HIDManager->HidP_GetCaps(preparsedData, &caps) != HIDP_STATUS_SUCCESS) nuclear@1: { nuclear@1: HIDManager->HidD_FreePreparsedData(preparsedData); nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: InputReportBufferLength = caps.InputReportByteLength; nuclear@1: OutputReportBufferLength = caps.OutputReportByteLength; nuclear@1: FeatureReportBufferLength= caps.FeatureReportByteLength; nuclear@1: HIDManager->HidD_FreePreparsedData(preparsedData); nuclear@1: nuclear@1: if (ReadBufferSize < InputReportBufferLength) nuclear@1: { nuclear@1: OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer.")); nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: // Get device desc. nuclear@1: if (!HIDManager->getFullDesc(Device, &DevDesc)) nuclear@1: { nuclear@1: OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device.")); nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: bool HIDDevice::openDevice() nuclear@1: { nuclear@1: memset(&ReadOverlapped, 0, sizeof(OVERLAPPED)); nuclear@1: nuclear@1: Device = HIDManager->CreateHIDFile(DevDesc.Path.ToCStr()); nuclear@1: if (Device == INVALID_HANDLE_VALUE) nuclear@1: { nuclear@1: OVR_DEBUG_LOG(("Failed 'CreateHIDFile' while opening device, error = 0x%X.", nuclear@1: ::GetLastError())); nuclear@1: Device = 0; nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: if (!HIDManager->HidD_SetNumInputBuffers(Device, 128)) nuclear@1: { nuclear@1: OVR_ASSERT_LOG(false, ("Failed 'HidD_SetNumInputBuffers' while initializing device.")); nuclear@1: ::CloseHandle(Device); nuclear@1: Device = 0; nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: nuclear@1: // Create a manual-reset non-signaled event. nuclear@1: ReadOverlapped.hEvent = ::CreateEvent(0, TRUE, FALSE, 0); nuclear@1: nuclear@1: if (!ReadOverlapped.hEvent) nuclear@1: { nuclear@1: OVR_ASSERT_LOG(false, ("Failed to create event.")); nuclear@1: ::CloseHandle(Device); nuclear@1: Device = 0; nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: if (!initInfo()) nuclear@1: { nuclear@1: OVR_ASSERT_LOG(false, ("Failed to get HIDDevice info.")); nuclear@1: nuclear@1: ::CloseHandle(ReadOverlapped.hEvent); nuclear@1: memset(&ReadOverlapped, 0, sizeof(OVERLAPPED)); nuclear@1: nuclear@1: ::CloseHandle(Device); nuclear@1: Device = 0; nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: if (!initializeRead()) nuclear@1: { nuclear@1: OVR_ASSERT_LOG(false, ("Failed to get intialize read for HIDDevice.")); nuclear@1: nuclear@1: ::CloseHandle(ReadOverlapped.hEvent); nuclear@1: memset(&ReadOverlapped, 0, sizeof(OVERLAPPED)); nuclear@1: nuclear@1: ::CloseHandle(Device); nuclear@1: Device = 0; nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: void HIDDevice::HIDShutdown() nuclear@1: { nuclear@1: nuclear@1: HIDManager->Manager->pThread->RemoveTicksNotifier(this); nuclear@1: HIDManager->Manager->pThread->RemoveMessageNotifier(this); nuclear@1: nuclear@1: closeDevice(); nuclear@1: LogText("OVR::Win32::HIDDevice - Closed '%s'\n", DevDesc.Path.ToCStr()); nuclear@1: } nuclear@1: nuclear@1: bool HIDDevice::initializeRead() nuclear@1: { nuclear@1: nuclear@1: if (!ReadRequested) nuclear@1: { nuclear@1: HIDManager->Manager->pThread->AddOverlappedEvent(this, ReadOverlapped.hEvent); nuclear@1: ReadRequested = true; nuclear@1: } nuclear@1: nuclear@1: // Read resets the event... nuclear@1: while(::ReadFile(Device, ReadBuffer, InputReportBufferLength, 0, &ReadOverlapped)) nuclear@1: { nuclear@1: processReadResult(); nuclear@1: } nuclear@1: nuclear@1: if (GetLastError() != ERROR_IO_PENDING) nuclear@1: { nuclear@1: // Some other error (such as unplugged). nuclear@1: closeDeviceOnIOError(); nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: bool HIDDevice::processReadResult() nuclear@1: { nuclear@1: nuclear@1: OVR_ASSERT(ReadRequested); nuclear@1: nuclear@1: DWORD bytesRead = 0; nuclear@1: nuclear@1: if (GetOverlappedResult(Device, &ReadOverlapped, &bytesRead, FALSE)) nuclear@1: { nuclear@1: // We've got data. nuclear@1: if (Handler) nuclear@1: { nuclear@1: Handler->OnInputReport(ReadBuffer, bytesRead); nuclear@1: } nuclear@1: nuclear@1: // TBD: Not needed? nuclear@1: // Event should be reset by Read call... nuclear@1: ReadOverlapped.Pointer = 0; nuclear@1: ReadOverlapped.Internal = 0; nuclear@1: ReadOverlapped.InternalHigh = 0; nuclear@1: return true; nuclear@1: } nuclear@1: else nuclear@1: { nuclear@1: if (GetLastError() != ERROR_IO_PENDING) nuclear@1: { nuclear@1: closeDeviceOnIOError(); nuclear@1: return false; nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: void HIDDevice::closeDevice() nuclear@1: { nuclear@1: if (ReadRequested) nuclear@1: { nuclear@1: HIDManager->Manager->pThread->RemoveOverlappedEvent(this, ReadOverlapped.hEvent); nuclear@1: ReadRequested = false; nuclear@1: // Must call this to avoid Win32 assertion; CloseHandle is not enough. nuclear@1: ::CancelIo(Device); nuclear@1: } nuclear@1: nuclear@1: ::CloseHandle(ReadOverlapped.hEvent); nuclear@1: memset(&ReadOverlapped, 0, sizeof(OVERLAPPED)); nuclear@1: nuclear@1: ::CloseHandle(Device); nuclear@1: Device = 0; nuclear@1: } nuclear@1: nuclear@1: void HIDDevice::closeDeviceOnIOError() nuclear@1: { nuclear@1: LogText("OVR::Win32::HIDDevice - Lost connection to '%s'\n", DevDesc.Path.ToCStr()); nuclear@1: closeDevice(); nuclear@1: } nuclear@1: nuclear@1: bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length) nuclear@1: { nuclear@1: if (!ReadRequested) nuclear@1: return false; nuclear@1: nuclear@1: return HIDManager->HidD_SetFeature(Device, data, (ULONG) length) != FALSE; nuclear@1: } nuclear@1: nuclear@1: bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length) nuclear@1: { nuclear@1: if (!ReadRequested) nuclear@1: return false; nuclear@1: nuclear@1: return HIDManager->HidD_GetFeature(Device, data, (ULONG) length) != FALSE; nuclear@1: } nuclear@1: nuclear@1: void HIDDevice::OnOverlappedEvent(HANDLE hevent) nuclear@1: { nuclear@1: OVR_UNUSED(hevent); nuclear@1: OVR_ASSERT(hevent == ReadOverlapped.hEvent); nuclear@1: nuclear@1: if (processReadResult()) nuclear@1: { nuclear@1: // Proceed to read again. nuclear@1: initializeRead(); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: UInt64 HIDDevice::OnTicks(UInt64 ticksMks) nuclear@1: { nuclear@1: if (Handler) nuclear@1: { nuclear@1: return Handler->OnTicks(ticksMks); nuclear@1: } nuclear@1: nuclear@1: return DeviceManagerThread::Notifier::OnTicks(ticksMks); nuclear@1: } nuclear@1: nuclear@1: bool HIDDevice::OnDeviceMessage(DeviceMessageType messageType, nuclear@1: const String& devicePath, nuclear@1: bool* error) nuclear@1: { nuclear@1: nuclear@1: // Is this the correct device? nuclear@1: if (DevDesc.Path.CompareNoCase(devicePath) != 0) nuclear@1: { nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: if (messageType == DeviceMessage_DeviceAdded && !Device) nuclear@1: { nuclear@1: // A closed device has been re-added. Try to reopen. nuclear@1: if (!openDevice()) nuclear@1: { nuclear@1: LogError("OVR::Win32::HIDDevice - Failed to reopen a device '%s' that was re-added.\n", devicePath.ToCStr()); nuclear@1: *error = true; nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: LogText("OVR::Win32::HIDDevice - Reopened device '%s'\n", devicePath.ToCStr()); nuclear@1: } nuclear@1: nuclear@1: HIDHandler::HIDDeviceMessageType handlerMessageType = HIDHandler::HIDDeviceMessage_DeviceAdded; nuclear@1: if (messageType == DeviceMessage_DeviceAdded) nuclear@1: { nuclear@1: } nuclear@1: else if (messageType == DeviceMessage_DeviceRemoved) nuclear@1: { nuclear@1: handlerMessageType = HIDHandler::HIDDeviceMessage_DeviceRemoved; nuclear@1: } nuclear@1: else nuclear@1: { nuclear@1: OVR_ASSERT(0); nuclear@1: } nuclear@1: nuclear@1: if (Handler) nuclear@1: { nuclear@1: Handler->OnDeviceMessage(handlerMessageType); nuclear@1: } nuclear@1: nuclear@1: *error = false; nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: HIDDeviceManager* HIDDeviceManager::CreateInternal(Win32::DeviceManager* devManager) nuclear@1: { nuclear@1: nuclear@1: if (!System::IsInitialized()) nuclear@1: { nuclear@1: // Use custom message, since Log is not yet installed. nuclear@1: OVR_DEBUG_STATEMENT(Log::GetDefaultLog()-> nuclear@1: LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); ); nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: Ptr manager = *new Win32::HIDDeviceManager(devManager); nuclear@1: nuclear@1: if (manager) nuclear@1: { nuclear@1: if (manager->Initialize()) nuclear@1: { nuclear@1: manager->AddRef(); nuclear@1: } nuclear@1: else nuclear@1: { nuclear@1: manager.Clear(); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: return manager.GetPtr(); nuclear@1: } nuclear@1: nuclear@1: } // namespace Win32 nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** Creation nuclear@1: nuclear@1: // Creates a new HIDDeviceManager and initializes OVR. nuclear@1: HIDDeviceManager* HIDDeviceManager::Create() nuclear@1: { nuclear@1: OVR_ASSERT_LOG(false, ("Standalone mode not implemented yet.")); nuclear@1: nuclear@1: if (!System::IsInitialized()) nuclear@1: { nuclear@1: // Use custom message, since Log is not yet installed. nuclear@1: OVR_DEBUG_STATEMENT(Log::GetDefaultLog()-> nuclear@1: LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); ); nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: Ptr manager = *new Win32::HIDDeviceManager(NULL); nuclear@1: nuclear@1: if (manager) nuclear@1: { nuclear@1: if (manager->Initialize()) nuclear@1: { nuclear@1: manager->AddRef(); nuclear@1: } nuclear@1: else nuclear@1: { nuclear@1: manager.Clear(); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: return manager.GetPtr(); nuclear@1: } nuclear@1: nuclear@1: } // namespace OVR