spicetools/external/stepmaniax-sdk/sdk/Windows/SMXDevice.h

137 lines
5.1 KiB
C++

#ifndef SMXDevice_h
#define SMXDevice_h
#include <windows.h>
#include <memory>
#include <functional>
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<SMXDevice> Create(shared_ptr<SMX::AutoCloseHandle> hEvent, SMX::Mutex &lock);
SMXDevice(shared_ptr<SMXDevice> &pSelf, shared_ptr<SMX::AutoCloseHandle> hEvent, SMX::Mutex &lock);
~SMXDevice();
bool OpenDeviceHandle(shared_ptr<SMX::AutoCloseHandle> pHandle, wstring &sError);
void CloseDevice();
shared_ptr<SMX::AutoCloseHandle> 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<void(int PadNumber, SMXUpdateCallbackReason reason)> pCallback);
// Return true if we're connected.
bool IsConnected() const;
// Send a raw command.
void SendCommand(string sCmd, function<void(string response)> pComplete=nullptr);
void SendCommandLocked(string sCmd, function<void(string response)> 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<SMX::AutoCloseHandle> m_hEvent;
SMX::Mutex &m_Lock;
function<void(int PadNumber, SMXUpdateCallbackReason reason)> m_pUpdateCallback;
weak_ptr<SMXDevice> m_pSelf;
shared_ptr<SMXDeviceConnection> 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<uint8_t> 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