diff --git a/src/openvr_plugin/driver_psmoveservice.cpp b/src/openvr_plugin/driver_psmoveservice.cpp index 7a2f4e61..d2fd2ea9 100644 --- a/src/openvr_plugin/driver_psmoveservice.cpp +++ b/src/openvr_plugin/driver_psmoveservice.cpp @@ -1270,6 +1270,8 @@ CPSMoveControllerLatest::CPSMoveControllerLatest( vr::IServerDriverHost * pDrive , m_pendingHapticPulseDuration(0) , m_lastTimeRumbleSent() , m_lastTimeRumbleSentValid(false) + , m_resetPoseButtonPressTime() + , m_bResetPoseRequestSent(false) , m_fVirtuallExtendControllersZ(0.0f) , m_fVirtuallExtendControllersY(0.0f) , m_bDelayAfterTouchpadPress(false) @@ -1700,32 +1702,68 @@ void CPSMoveControllerLatest::UpdateControllerState() { const ClientPSMoveView &clientView = m_controller_view->GetPSMoveView(); - bool bStartWasPressed = (m_ControllerState.ulButtonPressed & vr::ButtonMaskFromId(psButtonIDToVRButtonID[k_EPSButtonID_Start])) > 0; - bool bSelectWasPressed = (m_ControllerState.ulButtonPressed & vr::ButtonMaskFromId(psButtonIDToVRButtonID[k_EPSButtonID_Select])) > 0; + const bool bStartRealignHMDTriggered = + (clientView.GetButtonStart() == PSMoveButton_PRESSED && clientView.GetButtonSelect() == PSMoveButton_PRESSED) || + (clientView.GetButtonStart() == PSMoveButton_PRESSED && clientView.GetButtonSelect() == PSMoveButton_DOWN) || + (clientView.GetButtonStart() == PSMoveButton_DOWN && clientView.GetButtonSelect() == PSMoveButton_PRESSED); + + // See if the recenter button has been held for the requisite amount of time + bool bRecenterRequestTriggered = false; + { + PSMoveButtonState resetPoseButtonState = clientView.GetButtonSelect(); - bool bSquareWasPressed = (m_ControllerState.ulButtonPressed & vr::ButtonMaskFromId(psButtonIDToVRButtonID[k_EPSButtonID_Square])) > 0; - bool bCrossWasPressed = (m_ControllerState.ulButtonPressed & vr::ButtonMaskFromId(psButtonIDToVRButtonID[k_EPSButtonID_Cross])) > 0; - bool bTriangleWasPressed = (m_ControllerState.ulButtonPressed & vr::ButtonMaskFromId(psButtonIDToVRButtonID[k_EPSButtonID_Triangle])) > 0; - bool bCircleWasPressed = (m_ControllerState.ulButtonPressed & vr::ButtonMaskFromId(psButtonIDToVRButtonID[k_EPSButtonID_Circle])) > 0; + switch (resetPoseButtonState) + { + case PSMoveButtonState::PSMoveButton_DOWN: + { + m_resetPoseButtonPressTime = std::chrono::high_resolution_clock::now(); + } break; + case PSMoveButtonState::PSMoveButton_PRESSED: + { + if (!m_bResetPoseRequestSent) + { + const float k_hold_duration_milli = 250.f; + std::chrono::time_point now = std::chrono::high_resolution_clock::now(); + std::chrono::duration pressDurationMilli = now - m_resetPoseButtonPressTime; + + if (pressDurationMilli.count() >= k_hold_duration_milli) + { + bRecenterRequestTriggered = true; + } + } + } break; + case PSMoveButtonState::PSMoveButton_UP: + { + m_bResetPoseRequestSent = false; + } break; + } + } // If start was just pressed while and select was held or vice versa, // recenter the controller orientation pose and start the realignment of the controller to HMD tracking space. - if ((clientView.GetButtonStart() == PSMoveButton_PRESSED && clientView.GetButtonSelect() == PSMoveButton_PRESSED) || - (clientView.GetButtonStart() == PSMoveButton_PRESSED && clientView.GetButtonSelect() == PSMoveButton_DOWN) || - (clientView.GetButtonStart() == PSMoveButton_DOWN && clientView.GetButtonSelect() == PSMoveButton_PRESSED) ) - + if (bStartRealignHMDTriggered) { + PSMoveFloatVector3 controllerBallPointedUpEuler = PSMoveFloatVector3::create((float)M_PI_2, 0.0f, 0.0f); + PSMoveQuaternion controllerBallPointedUpQuat = PSMoveQuaternion::create(controllerBallPointedUpEuler); + #if LOG_REALIGN_TO_HMD != 0 - DriverLog("CPSMoveControllerLatest::UpdateControllerState(): Calling StartRealignHMDTrackingSpace() in response to controller chord.\n"); + DriverLog("CPSMoveControllerLatest::UpdateControllerState(): Calling StartRealignHMDTrackingSpace() in response to controller chord.\n"); #endif - PSMoveFloatVector3 controllerBallPointedUpEuler = PSMoveFloatVector3::create((float)M_PI_2, 0.0f, 0.0f); - PSMoveQuaternion controllerBallPointedUpQuat = PSMoveQuaternion::create(controllerBallPointedUpEuler); - ClientPSMoveAPI::reset_pose(m_controller_view, controllerBallPointedUpQuat); + ClientPSMoveAPI::eat_response(ClientPSMoveAPI::reset_pose(m_controller_view, controllerBallPointedUpQuat)); + m_bResetPoseRequestSent = true; StartRealignHMDTrackingSpace(); } - else { + else if (bRecenterRequestTriggered) + { + DriverLog("CPSMoveControllerLatest::UpdateControllerState(): Calling ClientPSMoveAPI::reset_pose() in response to controller button press.\n"); + + ClientPSMoveAPI::eat_response(ClientPSMoveAPI::reset_pose(m_controller_view, PSMoveQuaternion::identity())); + m_bResetPoseRequestSent = true; + } + else + { m_touchpadDirectionsUsed = false; UpdateControllerStateFromPsMoveButtonState(k_EPSButtonID_Circle, clientView.GetButtonCircle(), &NewState); UpdateControllerStateFromPsMoveButtonState(k_EPSButtonID_Cross, clientView.GetButtonCross(), &NewState); diff --git a/src/openvr_plugin/driver_psmoveservice.h b/src/openvr_plugin/driver_psmoveservice.h index 75bdc9dd..f22172a7 100644 --- a/src/openvr_plugin/driver_psmoveservice.h +++ b/src/openvr_plugin/driver_psmoveservice.h @@ -261,6 +261,9 @@ class CPSMoveControllerLatest : public CPSMoveTrackedDeviceLatest, public vr::IV std::chrono::time_point m_lastTouchpadPress; bool m_touchpadDirectionsUsed; + std::chrono::time_point m_resetPoseButtonPressTime; + bool m_bResetPoseRequestSent; + // Button Remapping vr::EVRButtonId psButtonIDToVRButtonID[k_EPSButtonID_Count]; eVRTouchpadDirection psButtonIDToVrTouchpadDirection[k_EPSButtonID_Count]; diff --git a/src/psmoveconfigtool/AppStage_ControllerSettings.cpp b/src/psmoveconfigtool/AppStage_ControllerSettings.cpp index 0b567d01..13522500 100644 --- a/src/psmoveconfigtool/AppStage_ControllerSettings.cpp +++ b/src/psmoveconfigtool/AppStage_ControllerSettings.cpp @@ -204,7 +204,9 @@ void AppStage_ControllerSettings::renderUI() { case ClientControllerView::eControllerType::PSMove: { - ImGui::BulletText("Controller Type: PSMove"); + //###HipsterSloth $TODO - The HID report for fetching the firmware revision doesn't appear to work + //ImGui::BulletText("Controller Type: PSMove (v%d.%d)", controllerInfo.FirmwareVersion, controllerInfo.FirmwareRevision); + ImGui::BulletText("Controller Type: PSMove"); } break; case ClientControllerView::eControllerType::PSNavi: { @@ -226,11 +228,18 @@ void AppStage_ControllerSettings::renderUI() if (controllerInfo.ControllerType == ClientControllerView::eControllerType::PSMove) { - if (ImGui::Button("Calibrate Magnetometer")) - { - m_app->getAppStage()->setBypassCalibrationFlag(false); - m_app->setAppStage(AppStage_MagnetometerCalibration::APP_STAGE_NAME); - } + if (controllerInfo.HasMagnetometer) + { + if (ImGui::Button("Calibrate Magnetometer")) + { + m_app->getAppStage()->setBypassCalibrationFlag(false); + m_app->setAppStage(AppStage_MagnetometerCalibration::APP_STAGE_NAME); + } + } + else + { + ImGui::TextDisabled("Magnetometer Disabled"); + } if (ImGui::Button("Calibrate Gyroscope")) { @@ -452,6 +461,9 @@ void AppStage_ControllerSettings::handle_controller_list_response( ControllerInfo.PairedToHost= ControllerResponse.assigned_host_serial().length() > 0 && ControllerResponse.assigned_host_serial() == thisPtr->m_hostSerial; + ControllerInfo.FirmwareVersion = ControllerResponse.firmware_version(); + ControllerInfo.FirmwareRevision = ControllerResponse.firmware_revision(); + ControllerInfo.HasMagnetometer = ControllerResponse.has_magnetometer(); // Add the controller to the appropriate connection list switch (ControllerResponse.connection_type()) diff --git a/src/psmoveconfigtool/AppStage_ControllerSettings.h b/src/psmoveconfigtool/AppStage_ControllerSettings.h index f7022f42..e4ae3ff6 100644 --- a/src/psmoveconfigtool/AppStage_ControllerSettings.h +++ b/src/psmoveconfigtool/AppStage_ControllerSettings.h @@ -14,12 +14,15 @@ class AppStage_ControllerSettings : public AppStage struct ControllerInfo { int ControllerID; + int FirmwareVersion; + int FirmwareRevision; ClientControllerView::eControllerType ControllerType; PSMoveTrackingColorType TrackingColorType; std::string DevicePath; std::string DeviceSerial; std::string AssignedHostSerial; bool PairedToHost; + bool HasMagnetometer; }; AppStage_ControllerSettings(class App *app); diff --git a/src/psmoveconfigtool/AppStage_GyroscopeCalibration.cpp b/src/psmoveconfigtool/AppStage_GyroscopeCalibration.cpp index 3da68c0b..5c54d6ff 100644 --- a/src/psmoveconfigtool/AppStage_GyroscopeCalibration.cpp +++ b/src/psmoveconfigtool/AppStage_GyroscopeCalibration.cpp @@ -157,6 +157,8 @@ AppStage_GyroscopeCalibration::AppStage_GyroscopeCalibration(App *app) , m_isControllerStreamActive(false) , m_lastControllerSeqNum(-1) , m_lastRawGyroscope() + , m_resetPoseButtonPressTime() + , m_bResetPoseRequestSent(false) , m_errorSamples(new GyroscopeErrorSamples) , m_scaleSamples(new GyroscopeScaleSamples) { @@ -440,6 +442,37 @@ void AppStage_GyroscopeCalibration::update() case eCalibrationMenuState::measureComplete: case eCalibrationMenuState::test: { + if (m_controllerView->GetControllerViewType() == ClientControllerView::PSMove) + { + PSMoveButtonState resetPoseButtonState= m_controllerView->GetPSMoveView().GetButtonSelect(); + + switch (resetPoseButtonState) + { + case PSMoveButtonState::PSMoveButton_DOWN: + { + m_resetPoseButtonPressTime= std::chrono::high_resolution_clock::now(); + } break; + case PSMoveButtonState::PSMoveButton_PRESSED: + { + if (!m_bResetPoseRequestSent) + { + const float k_hold_duration_milli = 250.f; + std::chrono::time_point now = std::chrono::high_resolution_clock::now(); + std::chrono::duration pressDurationMilli = now - m_resetPoseButtonPressTime; + + if (pressDurationMilli.count() >= k_hold_duration_milli) + { + ClientPSMoveAPI::eat_response(ClientPSMoveAPI::reset_pose(m_controllerView, PSMoveQuaternion::identity())); + m_bResetPoseRequestSent = true; + } + } + } break; + case PSMoveButtonState::PSMoveButton_UP: + { + m_bResetPoseRequestSent = false; + } break; + } + } } break; default: assert(0 && "unreachable"); @@ -686,7 +719,7 @@ void AppStage_GyroscopeCalibration::renderUI() case eCalibrationMenuState::test: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); - ImGui::SetNextWindowSize(ImVec2(k_panel_width, 80)); + ImGui::SetNextWindowSize(ImVec2(k_panel_width, 120)); ImGui::Begin(k_window_title, nullptr, window_flags); if (m_bBypassCalibration) @@ -698,6 +731,13 @@ void AppStage_GyroscopeCalibration::renderUI() ImGui::Text("Calibration of Controller ID #%d complete!", m_controllerView->GetControllerID()); } + if (m_controllerView->GetControllerViewType() == ClientControllerView::PSMove) + { + ImGui::TextWrapped( + "[Hold the Select button with controller pointed forward\n" \ + "to recenter the controller]"); + } + if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); diff --git a/src/psmoveconfigtool/AppStage_GyroscopeCalibration.h b/src/psmoveconfigtool/AppStage_GyroscopeCalibration.h index 628ba0ce..56de846b 100644 --- a/src/psmoveconfigtool/AppStage_GyroscopeCalibration.h +++ b/src/psmoveconfigtool/AppStage_GyroscopeCalibration.h @@ -69,6 +69,9 @@ class AppStage_GyroscopeCalibration : public AppStage std::chrono::time_point m_stableStartTime; bool m_bIsStable; + std::chrono::time_point m_resetPoseButtonPressTime; + bool m_bResetPoseRequestSent; + struct GyroscopeErrorSamples *m_errorSamples; struct GyroscopeScaleSamples *m_scaleSamples; }; diff --git a/src/psmoveconfigtool/AppStage_MagnetometerCalibration.cpp b/src/psmoveconfigtool/AppStage_MagnetometerCalibration.cpp index 058151e5..c133443d 100644 --- a/src/psmoveconfigtool/AppStage_MagnetometerCalibration.cpp +++ b/src/psmoveconfigtool/AppStage_MagnetometerCalibration.cpp @@ -67,6 +67,8 @@ AppStage_MagnetometerCalibration::AppStage_MagnetometerCalibration(App *app) , m_led_color_b(0) , m_stableStartTime() , m_bIsStable(false) + , m_resetPoseButtonPressTime() + , m_bResetPoseRequestSent(false) , m_identityPoseMVectorSum() , m_identityPoseSampleCount(0) { @@ -352,6 +354,37 @@ void AppStage_MagnetometerCalibration::update() } break; case eCalibrationMenuState::complete: { + if (m_controllerView->GetControllerViewType() == ClientControllerView::PSMove) + { + PSMoveButtonState resetPoseButtonState = m_controllerView->GetPSMoveView().GetButtonSelect(); + + switch (resetPoseButtonState) + { + case PSMoveButtonState::PSMoveButton_DOWN: + { + m_resetPoseButtonPressTime = std::chrono::high_resolution_clock::now(); + } break; + case PSMoveButtonState::PSMoveButton_PRESSED: + { + if (!m_bResetPoseRequestSent) + { + const float k_hold_duration_milli = 250.f; + std::chrono::time_point now = std::chrono::high_resolution_clock::now(); + std::chrono::duration pressDurationMilli = now - m_resetPoseButtonPressTime; + + if (pressDurationMilli.count() >= k_hold_duration_milli) + { + ClientPSMoveAPI::eat_response(ClientPSMoveAPI::reset_pose(m_controllerView, PSMoveQuaternion::identity())); + m_bResetPoseRequestSent = true; + } + } + } break; + case PSMoveButtonState::PSMoveButton_UP: + { + m_bResetPoseRequestSent = false; + } break; + } + } } break; case eCalibrationMenuState::pendingExit: { @@ -739,7 +772,7 @@ void AppStage_MagnetometerCalibration::renderUI() case eCalibrationMenuState::complete: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); - ImGui::SetNextWindowSize(ImVec2(k_panel_width, 80)); + ImGui::SetNextWindowSize(ImVec2(k_panel_width, 120)); ImGui::Begin(k_window_title, nullptr, window_flags); if (m_bBypassCalibration) @@ -751,6 +784,10 @@ void AppStage_MagnetometerCalibration::renderUI() ImGui::Text("Calibration of Controller ID #%d complete!", m_controllerView->GetControllerID()); } + ImGui::TextWrapped( + "[Hold the Select button with controller pointed forward\n" \ + "to recenter the controller]"); + if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); diff --git a/src/psmoveconfigtool/AppStage_MagnetometerCalibration.h b/src/psmoveconfigtool/AppStage_MagnetometerCalibration.h index 51e7dcc0..ab00413b 100644 --- a/src/psmoveconfigtool/AppStage_MagnetometerCalibration.h +++ b/src/psmoveconfigtool/AppStage_MagnetometerCalibration.h @@ -102,6 +102,9 @@ class AppStage_MagnetometerCalibration : public AppStage std::chrono::time_point m_stableStartTime; bool m_bIsStable; + std::chrono::time_point m_resetPoseButtonPressTime; + bool m_bResetPoseRequestSent; + PSMoveIntVector3 m_identityPoseMVectorSum; int m_identityPoseSampleCount; }; diff --git a/src/psmoveprotocol/PSMoveProtocol.proto b/src/psmoveprotocol/PSMoveProtocol.proto index a26dc12b..9256a59e 100644 --- a/src/psmoveprotocol/PSMoveProtocol.proto +++ b/src/psmoveprotocol/PSMoveProtocol.proto @@ -346,6 +346,9 @@ message Response { string device_path = 5; string device_serial = 6; string assigned_host_serial = 7; + int32 firmware_version = 8; + int32 firmware_revision = 9; + bool has_magnetometer = 10; } repeated ControllerInfo controllers = 1; string host_serial = 2; diff --git a/src/psmoveservice/Device/Manager/ControllerManager.cpp b/src/psmoveservice/Device/Manager/ControllerManager.cpp index 4754fe87..3578f5a0 100644 --- a/src/psmoveservice/Device/Manager/ControllerManager.cpp +++ b/src/psmoveservice/Device/Manager/ControllerManager.cpp @@ -3,6 +3,7 @@ #include "BluetoothQueries.h" #include "ControllerDeviceEnumerator.h" #include "OrientationFilter.h" +#include "PSMoveProtocol.pb.h" #include "ServerLog.h" #include "ServerControllerView.h" #include "ServerDeviceView.h" @@ -95,6 +96,11 @@ ControllerManager::allocate_device_view(int device_id) return new ServerControllerView(device_id); } +int ControllerManager::getListUpdatedResponseType() +{ + return PSMoveProtocol::Response_ResponseType_CONTROLLER_LIST_UPDATED; +} + void ControllerManager::setControllerRumble( int controller_id, diff --git a/src/psmoveservice/Device/Manager/ControllerManager.h b/src/psmoveservice/Device/Manager/ControllerManager.h index 3cbff9c0..747eda54 100644 --- a/src/psmoveservice/Device/Manager/ControllerManager.h +++ b/src/psmoveservice/Device/Manager/ControllerManager.h @@ -53,11 +53,7 @@ class ControllerManager : public DeviceTypeManager class DeviceEnumerator *allocate_device_enumerator() override; void free_device_enumerator(class DeviceEnumerator *) override; ServerDeviceView *allocate_device_view(int device_id) override; - - const PSMoveProtocol::Response_ResponseType getListUpdatedResponseType() override - { - return ControllerManager::k_list_udpated_response_type; - } + int getListUpdatedResponseType() override; private: static const PSMoveProtocol::Response_ResponseType k_list_udpated_response_type = PSMoveProtocol::Response_ResponseType_CONTROLLER_LIST_UPDATED; diff --git a/src/psmoveservice/Device/Manager/DeviceTypeManager.cpp b/src/psmoveservice/Device/Manager/DeviceTypeManager.cpp index 86d47a52..d6970491 100644 --- a/src/psmoveservice/Device/Manager/DeviceTypeManager.cpp +++ b/src/psmoveservice/Device/Manager/DeviceTypeManager.cpp @@ -1,6 +1,7 @@ //-- includes ----- #include "DeviceTypeManager.h" #include "DeviceEnumerator.h" +#include "PSMoveProtocol.pb.h" #include "ServerLog.h" #include "ServerDeviceView.h" #include "ServerNetworkManager.h" @@ -218,7 +219,7 @@ void DeviceTypeManager::send_device_list_changed_notification() { ResponsePtr response(new PSMoveProtocol::Response); - response->set_type(getListUpdatedResponseType()); + response->set_type(static_cast(getListUpdatedResponseType())); response->set_request_id(-1); response->set_result_code(PSMoveProtocol::Response_ResultCode_RESULT_OK); diff --git a/src/psmoveservice/Device/Manager/DeviceTypeManager.h b/src/psmoveservice/Device/Manager/DeviceTypeManager.h index 4c345d85..8e2d787d 100644 --- a/src/psmoveservice/Device/Manager/DeviceTypeManager.h +++ b/src/psmoveservice/Device/Manager/DeviceTypeManager.h @@ -4,7 +4,6 @@ //-- includes ----- #include #include -#include "PSMoveProtocol.pb.h" //-- typedefs ----- class ServerDeviceView; @@ -56,7 +55,7 @@ class DeviceTypeManager void send_device_list_changed_notification(); - virtual const PSMoveProtocol::Response_ResponseType getListUpdatedResponseType() = 0; + virtual int getListUpdatedResponseType() = 0; int find_first_closed_device_device_id(); int find_open_device_device_id(const class DeviceEnumerator *enumerator); diff --git a/src/psmoveservice/Device/Manager/TrackerManager.cpp b/src/psmoveservice/Device/Manager/TrackerManager.cpp index 46d0f19a..4b671490 100644 --- a/src/psmoveservice/Device/Manager/TrackerManager.cpp +++ b/src/psmoveservice/Device/Manager/TrackerManager.cpp @@ -4,6 +4,7 @@ #include "ServerLog.h" #include "ServerTrackerView.h" #include "ServerDeviceView.h" +#include "PSMoveProtocol.pb.h" //-- constants ----- @@ -156,3 +157,7 @@ TrackerManager::getTrackerViewPtr(int device_id) return std::static_pointer_cast(m_deviceViews[device_id]); } +int TrackerManager::getListUpdatedResponseType() +{ + return PSMoveProtocol::Response_ResponseType_TRACKER_LIST_UPDATED; +} \ No newline at end of file diff --git a/src/psmoveservice/Device/Manager/TrackerManager.h b/src/psmoveservice/Device/Manager/TrackerManager.h index ab71f823..ecf018fc 100644 --- a/src/psmoveservice/Device/Manager/TrackerManager.h +++ b/src/psmoveservice/Device/Manager/TrackerManager.h @@ -7,7 +7,6 @@ #include "DeviceEnumerator.h" #include "DeviceInterface.h" #include "PSMoveConfig.h" -#include "PSMoveProtocol.pb.h" //-- typedefs ----- @@ -90,15 +89,9 @@ class TrackerManager : public DeviceTypeManager DeviceEnumerator *allocate_device_enumerator() override; void free_device_enumerator(DeviceEnumerator *) override; ServerDeviceView *allocate_device_view(int device_id) override; - - const PSMoveProtocol::Response_ResponseType getListUpdatedResponseType() override - { - return TrackerManager::k_list_udpated_response_type; - } + int getListUpdatedResponseType() override; private: - static const PSMoveProtocol::Response_ResponseType k_list_udpated_response_type = PSMoveProtocol::Response_ResponseType_TRACKER_LIST_UPDATED; - TrackerManagerConfig cfg; bool m_tracker_list_dirty; }; diff --git a/src/psmoveservice/Device/View/ServerControllerView.cpp b/src/psmoveservice/Device/View/ServerControllerView.cpp index 2a88a6d8..deb85f54 100644 --- a/src/psmoveservice/Device/View/ServerControllerView.cpp +++ b/src/psmoveservice/Device/View/ServerControllerView.cpp @@ -1427,8 +1427,8 @@ init_filters_for_psmove( orientation_filter->setFilterSpace(filterSpace); - // Use the complementary MARG fusion filter by default - orientation_filter->setFusionType(OrientationFilter::FusionTypeComplementaryMARG); + // Use the complementary MARG fusion filter by default + orientation_filter->setFusionType(OrientationFilter::FusionTypeComplementaryMARG); orientation_filter->setGyroscopeError(psmove_config->gyro_variance); orientation_filter->setGyroscopeDrift(psmove_config->gyro_drift); } diff --git a/src/psmoveservice/PSMoveController/PSMoveController.cpp b/src/psmoveservice/PSMoveController/PSMoveController.cpp index 7c4fdc1e..38375d8f 100644 --- a/src/psmoveservice/PSMoveController/PSMoveController.cpp +++ b/src/psmoveservice/PSMoveController/PSMoveController.cpp @@ -46,6 +46,8 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include #ifdef _WIN32 #define _USE_MATH_DEFINES #endif @@ -197,6 +199,10 @@ PSMoveControllerConfig::config2ptree() pt.put("is_valid", is_valid); pt.put("version", PSMoveControllerConfig::CONFIG_VERSION); + pt.put("firmware_version", firmware_version); + pt.put("bt_firmware_version", bt_firmware_version); + pt.put("firmware_revision", firmware_revision); + pt.put("prediction_time", prediction_time); pt.put("max_poll_failure_count", max_poll_failure_count); @@ -263,6 +269,10 @@ PSMoveControllerConfig::ptree2config(const boost::property_tree::ptree &pt) { is_valid = pt.get("is_valid", false); + firmware_version = pt.get("firmware_version", 0); + bt_firmware_version = pt.get("bt_firmware_version", 0); + firmware_revision = pt.get("firmware_revision", 0); + prediction_time = pt.get("prediction_time", 0.f); max_poll_failure_count = pt.get("max_poll_failure_count", 100); @@ -352,6 +362,7 @@ PSMoveController::PSMoveController() , Rumble(0) , bWriteStateDirty(false) , NextPollSequenceNumber(0) + , SupportsMagnetometer(false) { HIDDetails.Handle = nullptr; HIDDetails.Handle_addr = nullptr; @@ -448,6 +459,9 @@ bool PSMoveController::open( if (getIsOpen()) // Controller was opened and has an index { + // Get the firmware revision being used + bool bSaveConfig= loadFirmwareInfo(); + // Get the bluetooth address #ifdef __APPLE__ // On my Mac, getting the bt feature report when connected via @@ -484,7 +498,7 @@ bool PSMoveController::open( } // Always save the config back out in case some defaults changed - cfg.save(); + bSaveConfig = true; success= true; } @@ -496,6 +510,45 @@ bool PSMoveController::open( success= false; } + // Poll the controller to see if it emits valid magnetometer data + // (Newer firmware doesn't support the magnetometer anymore) + if (success && IsBluetooth) + { + const int k_max_poll_attempts = 10; + int poll_count = 0; + bool bReadData = false; + + for (poll_count = 0; poll_count < k_max_poll_attempts && !bReadData; ++poll_count) + { + if (poll() == IDeviceInterface::ePollResult::_PollResultSuccessNewData) + { + const PSMoveControllerState *ControllerState = static_cast(getState()); + + SupportsMagnetometer = + ControllerState->RawMag[0] != 0 || + ControllerState->RawMag[1] != 0 || + ControllerState->RawMag[2] != 0; + bReadData= true; + } + else + { + const std::chrono::milliseconds k_WaitForDataMilliseconds(5); + + std::this_thread::sleep_for(k_WaitForDataMilliseconds); + } + } + + if (poll_count >= k_max_poll_attempts) + { + SERVER_LOG_ERROR("PSMoveController::open") << "Failed to open read initial controller state after " << k_max_poll_attempts << " attempts."; + } + } + + if (bSaveConfig) + { + cfg.save(); + } + // Reset the polling sequence counter NextPollSequenceNumber= 0; } @@ -859,6 +912,71 @@ PSMoveController::loadCalibration() cfg.is_valid= is_valid; } +bool +PSMoveController::loadFirmwareInfo() +{ + bool bFirmwareInfoValid = false; + + unsigned char buf[14]; + int res; + int expected_res = sizeof(buf) - 1; + unsigned char *p = buf; + + memset(buf, 0, sizeof(buf)); + buf[0] = PSMove_Req_GetFirmwareInfo; + + res = hid_get_feature_report(HIDDetails.Handle, buf, sizeof(buf)); + + /** + * The Bluetooth report contains the Report ID as additional first byte + * while the USB report does not. So we need to check the current connection + * type in order to determine the correct offset for reading from the report + * buffer. + **/ + + if (getIsBluetooth()) + { + expected_res += 1; + p = buf + 1; + } + + if (res == expected_res) + { + // NOTE: Each field in the report is stored in Big-Endian byte order + cfg.firmware_version = (p[0] << 8) | p[1]; + cfg.firmware_revision = (p[2] << 8) | p[3]; + cfg.bt_firmware_version = (p[4] << 8) | p[5]; + + bFirmwareInfoValid = true; + } + + return bFirmwareInfoValid; +} + +bool +PSMoveController::enableDFUMode() +{ + unsigned char buf[10]; + int res; + char mode_magic_val; + + if (getIsBluetooth()) + { + mode_magic_val = 0x43; + } + else + { + mode_magic_val = 0x42; + } + + memset(buf, 0, sizeof(buf)); + buf[0] = PSMove_Req_SetDFUMode; + buf[1] = mode_magic_val; + res = hid_send_feature_report(HIDDetails.Handle, buf, sizeof(buf)); + + return (res == sizeof(buf)); +} + IControllerInterface::ePollResult PSMoveController::poll() { diff --git a/src/psmoveservice/PSMoveController/PSMoveController.h b/src/psmoveservice/PSMoveController/PSMoveController.h index 745022c2..ab3b64dd 100644 --- a/src/psmoveservice/PSMoveController/PSMoveController.h +++ b/src/psmoveservice/PSMoveController/PSMoveController.h @@ -31,6 +31,9 @@ class PSMoveControllerConfig : public PSMoveConfig : PSMoveConfig(fnamebase) , is_valid(false) , version(CONFIG_VERSION) + , firmware_version(0) + , bt_firmware_version(0) + , firmware_revision(0) , max_poll_failure_count(100) , cal_ag_xyz_kb({{ {{ {{0, 0}}, {{0, 0}}, {{0, 0}} }}, @@ -63,7 +66,18 @@ class PSMoveControllerConfig : public PSMoveConfig bool is_valid; long version; + + // Move's firmware version number + unsigned short firmware_version; + + // Move Bluetooth module's firmware version number + unsigned short bt_firmware_version; + + // Move's firmware revision number + unsigned short firmware_revision; + long max_poll_failure_count; + std::array, 3>, 2> cal_ag_xyz_kb; CommonDeviceVector magnetometer_identity; CommonDeviceVector magnetometer_center; @@ -208,22 +222,21 @@ class PSMoveController : public IControllerInterface { float getTempCelsius() const; static CommonDeviceState::eDeviceType getDeviceTypeStatic() { return CommonDeviceState::PSMove; } - - + bool getSupportsMagnetometer() const + { return SupportsMagnetometer; } const unsigned long getLEDPWMFrequency() const - { - return LedPWMF; - } + { return LedPWMF; } - // -- Setters bool setLED(unsigned char r, unsigned char g, unsigned char b); // 0x00..0xff. TODO: vec3 bool setLEDPWMFrequency(unsigned long freq); // 733..24e6 bool setRumbleIntensity(unsigned char value); + bool enableDFUMode(); // Device Firmware Update mode private: bool getBTAddress(std::string& host, std::string& controller); void loadCalibration(); // Use USB or file if on BT + bool loadFirmwareInfo(); bool writeDataOut(); // Setters will call this @@ -231,6 +244,7 @@ class PSMoveController : public IControllerInterface { PSMoveControllerConfig cfg; PSMoveHIDDetails HIDDetails; bool IsBluetooth; // true if valid serial number on device opening + bool SupportsMagnetometer; // true if controller emits valid magnetometer data // Cached Setter State unsigned char LedR, LedG, LedB; diff --git a/src/psmoveservice/Server/PSMoveService.cpp b/src/psmoveservice/Server/PSMoveService.cpp index 01a8dc20..1bbc8510 100644 --- a/src/psmoveservice/Server/PSMoveService.cpp +++ b/src/psmoveservice/Server/PSMoveService.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include // provide setup example for windows service @@ -21,8 +23,6 @@ #include "setup/windows/setup/service_setup.hpp" #endif // defined(BOOST_WINDOWS_API) -using namespace boost; - //-- constants ----- #if defined(BOOST_POSIX_API) #define DAEMON_RUNNING_DIR "/tmp" @@ -53,7 +53,7 @@ class PSMoveServiceImpl } /// Entry point into boost::application - int operator()(application::context& context) + int operator()(boost::application::context& context) { BOOST_APPLICATION_FEATURE_SELECT @@ -62,18 +62,18 @@ class PSMoveServiceImpl { if (startup()) { - m_status = context.find(); + m_status = context.find(); const TrackerManagerConfig &cfg = DeviceManager::getInstance()->m_tracker_manager->getConfig(); - while (m_status->state() != application::status::stoped) + while (m_status->state() != boost::application::status::stoped) { - if (m_status->state() != application::status::paused) + if (m_status->state() != boost::application::status::paused) { update(); } - boost::this_thread::sleep(boost::posix_time::milliseconds(cfg.tracker_sleep_ms)); + std::this_thread::sleep_for(std::chrono::milliseconds(cfg.tracker_sleep_ms)); } } else @@ -99,34 +99,34 @@ class PSMoveServiceImpl return 0; } - bool stop(application::context& context) + bool stop(boost::application::context& context) { - if (m_status->state() != application::status::stoped) + if (m_status->state() != boost::application::status::stoped) { SERVER_LOG_WARNING("PSMoveService") << "Received stop request. Stopping Service."; - m_status->state(application::status::stoped); + m_status->state(boost::application::status::stoped); } return true; } - bool pause(application::context& context) + bool pause(boost::application::context& context) { - if (m_status->state() == application::status::running) + if (m_status->state() == boost::application::status::running) { SERVER_LOG_WARNING("PSMoveService") << "Received pause request. Pausing Service."; - m_status->state(application::status::paused); + m_status->state(boost::application::status::paused); } return true; } - bool resume(application::context& context) + bool resume(boost::application::context& context) { - if (m_status->state() == application::status::paused) + if (m_status->state() == boost::application::status::paused) { SERVER_LOG_WARNING("PSMoveService") << "Received resume request. Resuming Service."; - m_status->state(application::status::running); + m_status->state(boost::application::status::running); } return true; @@ -203,7 +203,7 @@ class PSMoveServiceImpl { // flag the service as stopped SERVER_LOG_WARNING("PSMoveService") << "Received termination signal. Stopping Service."; - m_status->state(application::status::stoped); + m_status->state(boost::application::status::stoped); } private: @@ -223,11 +223,11 @@ class PSMoveServiceImpl ServerNetworkManager m_network_manager; // Whether the application should keep running or not - std::shared_ptr m_status; + std::shared_ptr m_status; }; static void parse_program_settings( - const program_options::variables_map &options_map, + const boost::program_options::variables_map &options_map, PSMoveService::ProgramSettings &settings) { if (options_map.count("log_level")) @@ -251,7 +251,7 @@ static void parse_program_settings( #if defined(BOOST_WINDOWS_API) bool win32_service_management_action( - const program_options::variables_map &options_map) + const boost::program_options::variables_map &options_map) { HMODULE hModule = GetModuleHandleW(NULL); CHAR path[MAX_PATH]; @@ -274,14 +274,14 @@ bool win32_service_management_action( } boost::system::error_code ec; - application::example::install_windows_service( - application::setup_arg(options_map["name"].as()), - application::setup_arg(options_map["display"].as()), - application::setup_arg(options_map["description"].as()), - application::setup_arg(exe_full_path), - application::setup_arg(std::string("")), // username - application::setup_arg(std::string("")), // password - application::setup_arg(service_options)).install(ec); + boost::application::example::install_windows_service( + boost::application::setup_arg(options_map["name"].as()), + boost::application::setup_arg(options_map["display"].as()), + boost::application::setup_arg(options_map["description"].as()), + boost::application::setup_arg(exe_full_path), + boost::application::setup_arg(std::string("")), // username + boost::application::setup_arg(std::string("")), // password + boost::application::setup_arg(service_options)).install(ec); std::cout << ec.message() << std::endl; @@ -291,9 +291,9 @@ bool win32_service_management_action( else if (options_map.count("-u")) { boost::system::error_code ec; - application::example::uninstall_windows_service( - application::setup_arg(options_map["name"].as()), - application::setup_arg(exe_full_path)).uninstall(ec); + boost::application::example::uninstall_windows_service( + boost::application::setup_arg(options_map["name"].as()), + boost::application::setup_arg(exe_full_path)).uninstall(ec); std::cout << ec.message() << std::endl; @@ -304,8 +304,8 @@ bool win32_service_management_action( { boost::system::error_code ec; bool exist = - application::example::check_windows_service( - application::setup_arg(options_map["name"].as())).exist(ec); + boost::application::example::check_windows_service( + boost::application::setup_arg(options_map["name"].as())).exist(ec); if(ec) { @@ -437,8 +437,8 @@ int PSMoveService::exec(int argc, char *argv[]) BOOST_APPLICATION_FEATURE_SELECT // Parse service options - program_options::variables_map options_map; - program_options::options_description desc; + boost::program_options::variables_map options_map; + boost::program_options::options_description desc; // Extract the executable name std::string exe_name = boost::filesystem::path(argv[0]).stem().string(); @@ -447,15 +447,15 @@ int PSMoveService::exec(int argc, char *argv[]) desc.add_options() ("help,h", "Shows help.") (",d", "Run as background daemon/service") - ("log_level,l", program_options::value(), "The level of logging to use: trace, debug, info, warning, error, fatal") - ("admin_password,p", program_options::value(), "Remember the admin password for this machine (optional)") + ("log_level,l", boost::program_options::value(), "The level of logging to use: trace, debug, info, warning, error, fatal") + ("admin_password,p", boost::program_options::value(), "Remember the admin password for this machine (optional)") #if defined(BOOST_WINDOWS_API) (",i", "install service") (",u", "uninstall service") (",c", "check service") - ("name", program_options::value()->default_value(exe_name), "service name") - ("display", program_options::value()->default_value("PSMove Service"), "service display name (optional, installation only)") - ("description", program_options::value()->default_value("Manages PSMove controller and broadcasts state to clients"), "service description (optional, installation only)") + ("name", boost::program_options::value()->default_value(exe_name), "service name") + ("display", boost::program_options::value()->default_value("PSMove Service"), "service display name (optional, installation only)") + ("description", boost::program_options::value()->default_value("Manages PSMove controller and broadcasts state to clients"), "service description (optional, installation only)") #endif // defined(BOOST_WINDOWS_API) ; @@ -463,7 +463,7 @@ int PSMoveService::exec(int argc, char *argv[]) try { // Validate the command line against the arguments description - program_options::store(program_options::parse_command_line(argc, argv, desc), options_map); + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), options_map); // Extract the options that should be stored in the program settings parse_program_settings(options_map, this->m_settings); @@ -507,49 +507,49 @@ int PSMoveService::exec(int argc, char *argv[]) try { PSMoveServiceImpl app; - application::context app_context; + boost::application::context app_context; // service aspects - app_context.insert( - BOOST_APPLICATION_FEATURE_NS_SELECT::make_shared(argc, argv)); + app_context.insert( + BOOST_APPLICATION_FEATURE_NS_SELECT::make_shared(argc, argv)); - app_context.insert( - BOOST_APPLICATION_FEATURE_NS_SELECT::make_shared(argc, argv)); + app_context.insert( + BOOST_APPLICATION_FEATURE_NS_SELECT::make_shared(argc, argv)); // add termination handler - application::handler<>::parameter_callback termination_callback + boost::application::handler<>::parameter_callback termination_callback = boost::bind(&PSMoveServiceImpl::stop, &app, _1); - app_context.insert( - BOOST_APPLICATION_FEATURE_NS_SELECT::make_shared(termination_callback)); + app_context.insert( + BOOST_APPLICATION_FEATURE_NS_SELECT::make_shared(termination_callback)); // To "pause/resume" works, is required to add the 2 handlers. #if defined(BOOST_WINDOWS_API) // windows only : add pause handler - application::handler<>::parameter_callback pause_callback + boost::application::handler<>::parameter_callback pause_callback = boost::bind(&PSMoveServiceImpl::pause, &app, _1); - app_context.insert( - BOOST_APPLICATION_FEATURE_NS_SELECT::make_shared(pause_callback)); + app_context.insert( + BOOST_APPLICATION_FEATURE_NS_SELECT::make_shared(pause_callback)); // windows only : add resume handler - application::handler<>::parameter_callback resume_callback + boost::application::handler<>::parameter_callback resume_callback = boost::bind(&PSMoveServiceImpl::resume, &app, _1); - app_context.insert( - BOOST_APPLICATION_FEATURE_NS_SELECT::make_shared(resume_callback)); + app_context.insert( + BOOST_APPLICATION_FEATURE_NS_SELECT::make_shared(resume_callback)); #endif // defined(BOOST_WINDOWS_API) // my common/server instantiation #if defined(BOOST_WINDOWS_API) if (options_map.count("-d")) { - return application::launch(app, app_context); + return boost::application::launch(app, app_context); } else #endif // defined(BOOST_WINDOWS_API) { - return application::launch(app, app_context); + return boost::application::launch(app, app_context); } } catch (boost::system::system_error& se) diff --git a/src/psmoveservice/Server/ServerRequestHandler.cpp b/src/psmoveservice/Server/ServerRequestHandler.cpp index 6f647f2b..7c07f9a1 100644 --- a/src/psmoveservice/Server/ServerRequestHandler.cpp +++ b/src/psmoveservice/Server/ServerRequestHandler.cpp @@ -460,16 +460,32 @@ class ServerRequestHandlerImpl { PSMoveProtocol::Response_ResultControllerList_ControllerInfo *controller_info= list->add_controllers(); + int firmware_version = 0; + int firmware_revision = 0; + bool has_magnetometer = false; + switch(controller_view->getControllerDeviceType()) { case CommonControllerState::PSMove: - controller_info->set_controller_type(PSMoveProtocol::PSMOVE); + { + const PSMoveController *psmove_controller = controller_view->castCheckedConst(); + const PSMoveControllerConfig *psmove_config= psmove_controller->getConfig(); + + controller_info->set_controller_type(PSMoveProtocol::PSMOVE); + firmware_version = psmove_config->firmware_version; + firmware_revision = psmove_config->firmware_revision; + has_magnetometer = psmove_controller->getSupportsMagnetometer(); + } break; case CommonControllerState::PSNavi: - controller_info->set_controller_type(PSMoveProtocol::PSNAVI); + { + controller_info->set_controller_type(PSMoveProtocol::PSNAVI); + } break; case CommonControllerState::PSDualShock4: - controller_info->set_controller_type(PSMoveProtocol::PSDUALSHOCK4); + { + controller_info->set_controller_type(PSMoveProtocol::PSDUALSHOCK4); + } break; default: assert(0 && "Unhandled controller type"); @@ -485,6 +501,9 @@ class ServerRequestHandlerImpl controller_info->set_device_path(controller_view->getUSBDevicePath()); controller_info->set_device_serial(controller_view->getSerial()); controller_info->set_assigned_host_serial(controller_view->getAssignedHostBluetoothAddress()); + controller_info->set_firmware_version(firmware_version); + controller_info->set_firmware_revision(firmware_revision); + controller_info->set_has_magnetometer(has_magnetometer); } } diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 12e3edc8..6d5f71bd 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -268,6 +268,92 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "Windows") ELSE() #Linux/Darwin ENDIF() +# +# Set Controller DFU Mode +# + +SET(DFU_CTRLR_SRC) +SET(DFU_CTRLR_INCL_DIRS) +SET(DFU_CTRLR_REQ_LIBS) + +# Dependencies + +# hidapi +include_directories(${ROOT_DIR}/thirdparty/hidapi/hidapi) +IF(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + set(HIDAPI_SRC ${ROOT_DIR}/thirdparty/hidapi/windows/hid.c) +ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(HIDAPI_SRC ${ROOT_DIR}/thirdparty/hidapi/mac/hid.c) +ELSE() + set(HIDAPI_SRC ${ROOT_DIR}/thirdparty/hidapi/linux/hid.c) +ENDIF() +list(APPEND DFU_CTRLR_SRC ${HIDAPI_SRC}) + +#Bluetooth +IF(${CMAKE_SYSTEM_NAME} MATCHES "Windows") +ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + list(APPEND DFU_CTRLR_SRC ${ROOT_DIR}/src/psmoveservice/Platform/BluetoothQueriesOSX.mm) +ELSE() +ENDIF() + +# Boost +# TODO: Eliminate boost::filesystem with C++14 +FIND_PACKAGE(Boost REQUIRED QUIET COMPONENTS atomic chrono filesystem program_options system thread) +list(APPEND DFU_CTRLR_INCL_DIRS ${Boost_INCLUDE_DIRS}) +list(APPEND DFU_CTRLR_REQ_LIBS ${Boost_LIBRARIES}) + +# Eigen math library +list(APPEND DFU_CTRLR_INCL_DIRS ${ROOT_DIR}/thirdparty/eigen/) + +# PSMoveController +# We are not including the PSMoveService target on purpose, because this only tests +# a small part of the service and should not depend on the whole thing building. +list(APPEND DFU_CTRLR_INCL_DIRS + ${ROOT_DIR}/src/psmovemath/ + ${ROOT_DIR}/src/psmoveservice/ + ${ROOT_DIR}/src/psmoveservice/Server + ${ROOT_DIR}/src/psmoveservice/Device/Enumerator + ${ROOT_DIR}/src/psmoveservice/Device/Interface + ${ROOT_DIR}/src/psmoveservice/Platform + ${ROOT_DIR}/src/psmoveservice/PSMoveConfig + ${ROOT_DIR}/src/psmoveservice/PSMoveController) +list(APPEND DFU_CTRLR_SRC + ${ROOT_DIR}/src/psmovemath/MathAlignment.h + ${ROOT_DIR}/src/psmovemath/MathAlignment.cpp + ${ROOT_DIR}/src/psmovemath/MathEigen.h + ${ROOT_DIR}/src/psmovemath/MathEigen.cpp + ${ROOT_DIR}/src/psmovemath/MathUtility.h + ${ROOT_DIR}/src/psmovemath/MathUtility.cpp + ${ROOT_DIR}/src/psmoveservice/Server/ServerLog.h + ${ROOT_DIR}/src/psmoveservice/Server/ServerLog.cpp + ${ROOT_DIR}/src/psmoveservice/Server/ServerUtility.h + ${ROOT_DIR}/src/psmoveservice/Server/ServerUtility.cpp + ${ROOT_DIR}/src/psmoveservice/Device/Enumerator/ControllerDeviceEnumerator.h + ${ROOT_DIR}/src/psmoveservice/Device/Enumerator/ControllerDeviceEnumerator.cpp + ${ROOT_DIR}/src/psmoveservice/Platform/BluetoothQueries.h + ${ROOT_DIR}/src/psmoveservice/PSMoveConfig/PSMoveConfig.h + ${ROOT_DIR}/src/psmoveservice/PSMoveConfig/PSMoveConfig.cpp + ${ROOT_DIR}/src/psmoveservice/PSMoveController/PSMoveController.h + ${ROOT_DIR}/src/psmoveservice/PSMoveController/PSMoveController.cpp) + +# psmoveprotocol +list(APPEND DFU_CTRLR_INCL_DIRS ${ROOT_DIR}/src/psmoveprotocol) +list(APPEND DFU_CTRLR_REQ_LIBS PSMoveProtocol) + +add_executable(set_controller_dfu_mode ${CMAKE_CURRENT_LIST_DIR}/set_controller_dfu_mode.cpp ${DFU_CTRLR_SRC}) +target_include_directories(set_controller_dfu_mode PUBLIC ${DFU_CTRLR_INCL_DIRS}) +target_link_libraries(set_controller_dfu_mode ${PLATFORM_LIBS} ${DFU_CTRLR_REQ_LIBS}) +SET_TARGET_PROPERTIES(set_controller_dfu_mode PROPERTIES FOLDER Test) + +# Install +IF(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + install(TARGETS set_controller_dfu_mode + RUNTIME DESTINATION ${ROOT_DIR}/${ARCH_LABEL}/bin + LIBRARY DESTINATION ${ROOT_DIR}/${ARCH_LABEL}/lib + ARCHIVE DESTINATION ${ROOT_DIR}/${ARCH_LABEL}/lib) +ELSE() #Linux/Darwin +ENDIF() + # # TEST_CONSOLE_CLIENT # diff --git a/src/tests/set_controller_dfu_mode.cpp b/src/tests/set_controller_dfu_mode.cpp new file mode 100644 index 00000000..67932612 --- /dev/null +++ b/src/tests/set_controller_dfu_mode.cpp @@ -0,0 +1,67 @@ +#include +#include +#include "PSMoveController.h" +#include "ServerLog.h" + +// For sleep +#ifdef _WIN32 +#include +#else +#include +#endif + +int main() +{ + int result = -1; + + log_init("info"); + + if (hid_init() != -1) + { + PSMoveController psmove; + + SERVER_LOG_INFO("main") << "Opening first PSMoveController..."; + + if (psmove.open()) + { + SERVER_LOG_INFO("main") << "Checking for USB connection..."; + + if (!psmove.getIsBluetooth()) + { + SERVER_LOG_INFO("main") << "Enabling USB DFU mode..."; + + if (psmove.enableDFUMode()) + { + SERVER_LOG_INFO("main") << "Success!"; + SERVER_LOG_INFO("main") << "Unplug the controller to reset it"; + } + else + { + SERVER_LOG_ERROR("main") << "Failed to enable DFU mode over USB."; + } + } + else + { + SERVER_LOG_ERROR("main") << "Controller connected via bluetooth!"; + SERVER_LOG_ERROR("main") << "Turn all all controllers and only plug in one controller via USB."; + } + + psmove.close(); + } + else + { + SERVER_LOG_ERROR("main") << "Failed to open controller"; + } + + // Tear-down hid api + hid_exit(); + } + else + { + SERVER_LOG_ERROR("main") << "Failed to initialize hidapi"; + } + + log_dispose(); + + return result; +} \ No newline at end of file