#pragma once
#include "env.h"
#include "p8-platform/threads/threads.h"
#include "adapter/AdapterCommunication.h"
#include "USBCECAdapterMessage.h"
namespace P8PLATFORM
{
class ISocket;
}
namespace CEC
{
class CCECProcessor;
class CAdapterPingThread;
class CAdapterEepromWriteThread;
class CUSBCECAdapterCommands;
class CCECAdapterMessageQueue;
class CCECAdapterMessage;
class CUSBCECAdapterCommunication : public IAdapterCommunication, public P8PLATFORM::CThread
{
friend class CUSBCECAdapterCommands;
friend class CCECAdapterMessageQueue;
friend class CAdapterEepromWriteThread;
public:
CUSBCECAdapterCommunication(IAdapterCommunicationCallback *callback, const char *strPort, uint16_t iBaudRate = CEC_SERIAL_DEFAULT_BAUDRATE);
virtual ~CUSBCECAdapterCommunication(void);
bool Open(uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT, bool bSkipChecks = false, bool bStartListening = true);
void Close(void);
bool IsOpen(void);
std::string GetError(void) const;
cec_adapter_message_state Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool bIsReply);
bool StartBootloader(void);
bool SetLogicalAddresses(const cec_logical_addresses &addresses);
cec_logical_addresses GetLogicalAddresses(void) const;
bool PingAdapter(void);
uint16_t GetFirmwareVersion(void);
uint32_t GetFirmwareBuildDate(void);
bool IsRunningLatestFirmware(void);
bool SaveConfiguration(const libcec_configuration &configuration);
bool SetAutoMode(bool automode);
bool GetConfiguration(libcec_configuration &configuration);
std::string GetPortName(void);
uint16_t GetPhysicalAddress(void);
bool SetControlledMode(bool controlled);
cec_vendor_id GetVendorId(void) { return CEC_VENDOR_UNKNOWN; }
bool SupportsSourceLogicalAddress(const cec_logical_address UNUSED(address)) { return true; }
cec_adapter_type GetAdapterType(void);
uint16_t GetAdapterVendorId(void) const;
uint16_t GetAdapterProductId(void) const;
void SetActiveSource(bool bSetTo, bool bClientUnregistered);
#if CEC_LIB_VERSION_MAJOR >= 5
bool GetStats(struct cec_adapter_stats* stats);
#endif
bool ProvidesExtendedResponse(void);
void OnRxSuccess(void);
void OnRxError(void);
void OnTxAck(void);
void OnTxNack(void);
void OnTxError(void);
void *Process(void);
private:
void ClearInputBytes(uint32_t iTimeout = CEC_CLEAR_INPUT_DEFAULT_WAIT);
bool SetLineTimeout(uint8_t iTimeout);
CCECAdapterMessage *SendCommand(cec_adapter_messagecode msgCode, CCECAdapterMessage ¶ms, bool bIsRetry = false);
void SetInitialised(bool bSetTo = true);
bool IsInitialised(void) const;
bool CheckAdapter(uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT);
bool HandlePoll(const CCECAdapterMessage &msg);
bool ReadFromDevice(uint32_t iTimeout, size_t iSize = 256);
bool WriteToDevice(CCECAdapterMessage *message);
void MarkAsWaiting(const cec_logical_address dest);
void ResetMessageQueue(void);
P8PLATFORM::ISocket * m_port;
mutable P8PLATFORM::CMutex m_mutex;
uint8_t m_iLineTimeout;
cec_logical_address m_lastPollDestination;
bool m_bInitialised;
bool m_bWaitingForAck[15];
CAdapterPingThread * m_pingThread;
CAdapterEepromWriteThread * m_eepromWriteThread;
CUSBCECAdapterCommands * m_commands;
CCECAdapterMessageQueue * m_adapterMessageQueue;
cec_logical_addresses m_logicalAddresses;
struct cec_adapter_stats m_stats;
P8PLATFORM::CMutex m_statsMutex;
P8PLATFORM::CMutex m_waitingMutex;
};
class CAdapterEepromWriteThread : public P8PLATFORM::CThread
{
public:
CAdapterEepromWriteThread(CUSBCECAdapterCommunication *com) :
m_com(com),
m_bWrite(false),
m_iLastEepromWrite(0),
m_iScheduleEepromWrite(0) {}
virtual ~CAdapterEepromWriteThread(void) {}
bool Write(void);
void* Process(void);
void Stop(void);
private:
CUSBCECAdapterCommunication *m_com;
bool m_bWrite;
P8PLATFORM::CCondition<bool> m_condition;
P8PLATFORM::CMutex m_mutex;
int64_t m_iLastEepromWrite;
int64_t m_iScheduleEepromWrite;
};
class CAdapterPingThread : public P8PLATFORM::CThread
{
public:
CAdapterPingThread(CUSBCECAdapterCommunication *com, uint32_t iTimeout) :
m_com(com),
m_timeout(iTimeout){}
virtual ~CAdapterPingThread(void) {}
void* Process(void);
private:
CUSBCECAdapterCommunication* m_com;
P8PLATFORM::CTimeout m_timeout;
};
};