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); }
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); }