#ifndef SMXDevice_h #define SMXDevice_h #include #include #include using namespace std; #include "Helpers.h" #include "../SMX.h" namespace SMX { class SMXDeviceConnection; // The high-level interface to a single controller. This is managed by SMXManager, and uses SMXDeviceConnection // for low-level USB communication. class SMXDevice { public: // Create an SMXDevice. // // lock is our serialization mutex. This is shared across SMXManager and all SMXDevices. // // hEvent is signalled when we have new packets to be sent, to wake the communications thread. The // device handle opened with OpenPort must also be monitored, to check when packets have been received // (or successfully sent). static shared_ptr Create(shared_ptr hEvent, SMX::Mutex &lock); SMXDevice(shared_ptr &pSelf, shared_ptr hEvent, SMX::Mutex &lock); ~SMXDevice(); bool OpenDeviceHandle(shared_ptr pHandle, wstring &sError); void CloseDevice(); shared_ptr GetDeviceHandle() const; // Set a function to be called when something changes on the device. This allows efficiently // detecting when a panel is pressed or other changes happen on the device. void SetUpdateCallback(function pCallback); // Return true if we're connected. bool IsConnected() const; // Send a raw command. void SendCommand(string sCmd, function pComplete=nullptr); void SendCommandLocked(string sCmd, function pComplete=nullptr); // Get basic info about the device. void GetInfo(SMXInfo &info); void GetInfoLocked(SMXInfo &info); // used by SMXManager // Return true if this device is configured as player 2. bool IsPlayer2Locked() const; // used by SMXManager // Get the configuration of the connected device (or the most recently read configuration if // we're not connected). bool GetConfig(SMXConfig &configOut); bool GetConfigLocked(SMXConfig &configOut); // Set the configuration of the connected device. // // This is asynchronous and returns immediately. void SetConfig(const SMXConfig &newConfig); // Return a mask of the panels currently pressed. uint16_t GetInputState() const; // Reset the configuration data to what the device used when it was first flashed. // GetConfig() will continue to return the previous configuration until this command // completes, which is signalled by a SMXUpdateCallback_FactoryResetCommandComplete callback. void FactoryReset(); // Force immediate fast recalibration. This is the same calibration that happens at // boot. This is only used for diagnostics, and the panels will normally auto-calibrate // on their own. void ForceRecalibration(); // Set the test mode of the connected device. // // This is asynchronous and returns immediately. void SetSensorTestMode(SensorTestMode mode); // Return the most recent test data we've received from the pad. Return false if we haven't // received test data since changing the test mode (or if we're not in a test mode). bool GetTestData(SMXSensorTestModeData &data); // Internal: // Update this device, processing received packets and sending any outbound packets. // m_Lock must be held. // // sError will be set on a communications error. The owner must close the device. void Update(wstring &sError); private: shared_ptr m_hEvent; SMX::Mutex &m_Lock; function m_pUpdateCallback; weak_ptr m_pSelf; shared_ptr m_pConnection; // The configuration we've read from the device. m_bHaveConfig is true if we've received // a configuration from the device since we've connected to it. SMXConfig config; vector rawConfig; bool m_bHaveConfig = false; double m_fDelayConfigUpdatesUntil = 0; // This is the configuration the user has set, if he's changed anything. We send this to // the device if m_bSendConfig is true. Once we send it once, m_bSendConfig is cleared, and // if we see a different configuration from the device again we won't re-send this. SMXConfig wanted_config; bool m_bSendConfig = false; bool m_bSendingConfig = false; bool m_bWaitingForConfigResponse = false; void CallUpdateCallback(SMXUpdateCallbackReason reason); void HandlePackets(); void SendConfig(); void CheckActive(); bool IsConnectedLocked() const; // Test/diagnostics mode handling. void UpdateSensorTestMode(); void HandleSensorTestDataResponse(const string &sReadBuffer); SensorTestMode m_WaitingForSensorTestModeResponse = SensorTestMode_Off; SensorTestMode m_SensorTestMode = SensorTestMode_Off; bool m_HaveSensorTestModeData = false; SMXSensorTestModeData m_SensorTestData; uint32_t m_SentSensorTestModeRequestAtTicks = 0; }; } #endif