#pragma once
#include "env.h"
#if defined(HAVE_RPI_API)
#include "adapter/AdapterCommunication.h"
#include "p8-platform/threads/threads.h"
#define RPI_ADAPTER_VID 0x2708
#define RPI_ADAPTER_PID 0x1001
extern "C" {
#include <interface/vmcs_host/vc_cecservice.h>
#include <interface/vchiq_arm/vchiq_if.h>
}
namespace CEC
{
class CRPiCECAdapterMessageQueue;
class CRPiCECAdapterCommunication : public IAdapterCommunication
{
public:
CRPiCECAdapterCommunication(IAdapterCommunicationCallback *callback);
virtual ~CRPiCECAdapterCommunication(void);
bool Open(uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT, bool bSkipChecks = false, bool bStartListening = true);
void Close(void);
bool IsOpen(void) { return m_bInitialised; };
std::string GetError(void) const;
cec_adapter_message_state Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool bIsReply);
bool SetLineTimeout(uint8_t UNUSED(iTimeout)) { return true; };
bool StartBootloader(void) { return false; };
bool SetLogicalAddresses(const cec_logical_addresses &addresses);
cec_logical_addresses GetLogicalAddresses(void) const;
bool PingAdapter(void) { return m_bInitialised; };
uint16_t GetFirmwareVersion(void);
uint32_t GetFirmwareBuildDate(void) { return 0; };
bool IsRunningLatestFirmware(void) { return true; };
bool SaveConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; };
bool GetConfiguration(libcec_configuration & UNUSED(configuration)) { return false; };
bool SetAutoMode(bool UNUSED(automode)) { return false; }
std::string GetPortName(void) { std::string strReturn("RPI"); return strReturn; };
uint16_t GetPhysicalAddress(void);
bool SetControlledMode(bool UNUSED(controlled)) { return true; };
cec_vendor_id GetVendorId(void) { return CEC_VENDOR_BROADCOM; }
bool SupportsSourceLogicalAddress(const cec_logical_address address) { return address > CECDEVICE_TV && address < CECDEVICE_BROADCAST; }
cec_adapter_type GetAdapterType(void) { return ADAPTERTYPE_RPI; };
uint16_t GetAdapterVendorId(void) const { return RPI_ADAPTER_VID; }
uint16_t GetAdapterProductId(void) const { return RPI_ADAPTER_PID; }
void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) {}
#if CEC_LIB_VERSION_MAJOR >= 5
bool GetStats(struct cec_adapter_stats* UNUSED(stats)) { return false; }
#endif
bool IsInitialised(void);
void OnDataReceived(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4);
void OnTVServiceCallback(uint32_t reason, uint32_t p0, uint32_t p1);
static void InitHost(void);
private:
cec_logical_address GetLogicalAddress(void) const;
bool UnregisterLogicalAddress(void);
bool RegisterLogicalAddress(const cec_logical_address address, uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT);
void SetDisableCallback(const bool disable);
bool m_bInitialised;
std::string m_strError;
CRPiCECAdapterMessageQueue *m_queue;
cec_logical_address m_logicalAddress;
bool m_bLogicalAddressChanged;
P8PLATFORM::CCondition<bool> m_logicalAddressCondition;
mutable P8PLATFORM::CMutex m_mutex;
VCHI_INSTANCE_T m_vchi_instance;
VCHI_CONNECTION_T * m_vchi_connection;
cec_logical_address m_previousLogicalAddress;
bool m_bLogicalAddressRegistered;
bool m_bDisableCallbacks;
};
};
#endif