static DWORD WINAPI ThreadProc(void* context)
{
	DeviceStatus* pDeviceStauts = static_cast<DeviceStatus*>(context);
	if (pDeviceStauts != NULL)
	{
		if (!pDeviceStauts->Initialize())
		{
			return 0;
		}

		while(Win32_DeviceManager::_bRunning)
		{
			pDeviceStauts->ProcessMessages();
		}

		pDeviceStauts->ShutDown();
	}
	return 0;
}
LRESULT CALLBACK DeviceStatus::WindowsMessageCallback(  HWND hwnd, 
                                                        UINT message, 
                                                        WPARAM wParam, 
                                                        LPARAM lParam)
{
	switch (message)
	{
	case WM_CREATE:
		{
			// Setup window user data with device status object pointer.
			LPCREATESTRUCT create_struct = reinterpret_cast<LPCREATESTRUCT>(lParam);
			void *lpCreateParam = create_struct->lpCreateParams;
			DeviceStatus *pDeviceStatus = reinterpret_cast<DeviceStatus*>(lpCreateParam);

			SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pDeviceStatus));
		}
		return 0;	// Return 0 for successfully handled WM_CREATE.

	case WM_DEVICECHANGE:
		{
			WORD loword = LOWORD(wParam);

			if (loword != DBT_DEVICEARRIVAL &&
				loword != DBT_DEVICEREMOVECOMPLETE) 
			{
				// Ignore messages other than device arrive and remove complete 
                // (we're not handling intermediate ones).
				return TRUE;	// Grant WM_DEVICECHANGE request.
			}

			DEV_BROADCAST_DEVICEINTERFACE* hdr;
			hdr = (DEV_BROADCAST_DEVICEINTERFACE*) lParam;

			if (hdr->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE) 
			{
				// Ignore non interface device messages.
				return TRUE;	// Grant WM_DEVICECHANGE request.
			}

			LONG_PTR userData = GetWindowLongPtr(hwnd, GWLP_USERDATA);
			OVR_ASSERT(userData != NULL);

			// Call callback on device messages object with the device path.
			DeviceStatus* pDeviceStatus = (DeviceStatus*) userData;
			String devicePath(hdr->dbcc_name);

            // check if HID device caused the event...
            if (pDeviceStatus->HidGuid == hdr->dbcc_classguid)
            {
                // check if recovery timer is already running; stop it and 
                // remove it, if so.
                pDeviceStatus->FindAndCleanupRecoveryTimer(devicePath);

                if (!pDeviceStatus->MessageCallback(loword, devicePath))
                {
                    // hmmm.... unsuccessful
                    if (loword == DBT_DEVICEARRIVAL)
                    {
                        // Windows sometimes may return errors ERROR_SHARING_VIOLATION and
                        // ERROR_FILE_NOT_FOUND when trying to open an USB device via
                        // CreateFile. Need to start a recovery timer that will try to 
                        // re-open the device again.
                        OVR_DEBUG_LOG(("Adding failed, recovering through a timer..."));
                        UINT_PTR tid = ::SetTimer(hwnd, ++pDeviceStatus->LastTimerId, 
                            USBRecoveryTimeInterval, NULL);
                        RecoveryTimerDesc rtDesc;
                        rtDesc.TimerId = tid;
                        rtDesc.DevicePath = devicePath;
                        rtDesc.NumAttempts= 0;
                        pDeviceStatus->RecoveryTimers.PushBack(rtDesc);
                        // wrap around the timer counter, avoid timerId == 0...
                        if (pDeviceStatus->LastTimerId + 1 == 0)
                            pDeviceStatus->LastTimerId = 0;
                    }
                }
            }
            // Check if Oculus HDMI device was plugged/unplugged, preliminary
            // filtering. (is there any way to get GUID? !AB)
            //else if (strstr(devicePath.ToCStr(), "DISPLAY#"))
            else if (strstr(devicePath.ToCStr(), "#OVR00"))
            {
                pDeviceStatus->MessageCallback(loword, devicePath);
            }
		}
		return TRUE;	// Grant WM_DEVICECHANGE request.

	case WM_TIMER:
		{
			if (wParam != 0)
			{
				LONG_PTR userData = GetWindowLongPtr(hwnd, GWLP_USERDATA);
				OVR_ASSERT(userData != NULL);

				// Call callback on device messages object with the device path.
				DeviceStatus* pDeviceStatus = (DeviceStatus*) userData;

                // Check if we have recovery timer running (actually, we must be!)
                UPInt rtIndex;
                RecoveryTimerDesc* prtDesc = pDeviceStatus->FindRecoveryTimer(wParam, &rtIndex);
				if (prtDesc)
				{
					if (pDeviceStatus->MessageCallback(DBT_DEVICEARRIVAL, prtDesc->DevicePath))
					{
                        OVR_DEBUG_LOG(("Recovered, adding is successful, cleaning up the timer..."));
                        // now it is successful, kill the timer and cleanup
                        pDeviceStatus->CleanupRecoveryTimer(rtIndex);
					}
                    else
                    {
                        if (++prtDesc->NumAttempts >= MaxUSBRecoveryAttempts)
                        {
                            OVR_DEBUG_LOG(("Failed to recover USB after %d attempts, path = '%s', aborting...",
                                prtDesc->NumAttempts, prtDesc->DevicePath.ToCStr()));
                            pDeviceStatus->CleanupRecoveryTimer(rtIndex);
                        }
                        else
                        {
                            OVR_DEBUG_LOG(("Failed to recover USB, %d attempts, path = '%s'",
                                prtDesc->NumAttempts, prtDesc->DevicePath.ToCStr()));
                        }
                    }
				}
			}
		}
		return 0;

	case WM_CLOSE:
		{
			LONG_PTR userData = GetWindowLongPtr(hwnd, GWLP_USERDATA);
			OVR_ASSERT(userData != NULL);
			DeviceStatus* pDeviceStatus = (DeviceStatus*) userData;
			pDeviceStatus->hMessageWindow = NULL;

			DestroyWindow(hwnd);
		}
		return 0;	// We processed the WM_CLOSE message.

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;	// We processed the WM_DESTROY message.
	}

	return DefWindowProc(hwnd, message, wParam, lParam);
}
Ejemplo n.º 3
0
LRESULT CALLBACK DeviceStatus::WindowsMessageCallback(  HWND hwnd, 
                                                        UINT message, 
                                                        WPARAM wParam, 
                                                        LPARAM lParam)
{

	switch (message)
	{
	case WM_CREATE:
		{
			// Setup window user data with device status object pointer.
			LPCREATESTRUCT create_struct = reinterpret_cast<LPCREATESTRUCT>(lParam);
			void *lpCreateParam = create_struct->lpCreateParams;
			DeviceStatus *pDeviceStatus = reinterpret_cast<DeviceStatus*>(lpCreateParam);

			SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pDeviceStatus));
		}
		return 0;	// Return 0 for successfully handled WM_CREATE.

	case WM_DEVICECHANGE:
		{
			WORD loword = LOWORD(wParam);

			if (loword != DBT_DEVICEARRIVAL &&
				loword != DBT_DEVICEREMOVECOMPLETE) 
			{
				// Ignore messages other than device arrive and remove complete 
                // (we're not handling intermediate ones).
				return TRUE;	// Grant WM_DEVICECHANGE request.
			}

			DEV_BROADCAST_DEVICEINTERFACE* hdr;
			hdr = (DEV_BROADCAST_DEVICEINTERFACE*) lParam;

			if (hdr->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE) 
			{
				// Ignore non interface device messages.
				return TRUE;	// Grant WM_DEVICECHANGE request.
			}

			LONG_PTR userData = GetWindowLongPtr(hwnd, GWLP_USERDATA);
			OVR_ASSERT(userData != NULL);

			// Call callback on device messages object with the device path.
			DeviceStatus* pDeviceStatus = (DeviceStatus*) userData;
			String devicePathStr(hdr->dbcc_name);
			pDeviceStatus->MessageCallback(loword, devicePathStr);
		}
		return TRUE;	// Grant WM_DEVICECHANGE request.

	case WM_CLOSE:
		{
			LONG_PTR userData = GetWindowLongPtr(hwnd, GWLP_USERDATA);
			OVR_ASSERT(userData != NULL);
			DeviceStatus* pDeviceStatus = (DeviceStatus*) userData;
			pDeviceStatus->hMessageWindow = NULL;

			DestroyWindow(hwnd);
		}
		return 0;	// We processed the WM_CLOSE message.

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;	// We processed the WM_DESTROY message.
	}

	return DefWindowProc(hwnd, message, wParam, lParam);
}