137 lines
5.1 KiB
C
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
|