cec: fixed - don't keep the mutex locked in CCECProcessor::Initialise()
[deb_libcec.git] / src / lib / AdapterCommunication.h
index f7dafa0250dbd1e5bc9030d9a62a4ae00ff17c50..97cd18d2f3b1debbc01207509dbe4ac94e4103d5 100644 (file)
  *     http://www.pulse-eight.net/
  */
 
-#include "../../include/CECExports.h"
-#include "util/threads.h"
+#include <cectypes.h>
+#include "platform/os.h"
 
-class CSerialPort;
+namespace PLATFORM
+{
+  class CSerialPort;
+}
 
 namespace CEC
 {
-  class CLibCEC;
+  typedef enum cec_adapter_message_state
+  {
+    ADAPTER_MESSAGE_STATE_UNKNOWN = 0,
+    ADAPTER_MESSAGE_STATE_WAITING,
+    ADAPTER_MESSAGE_STATE_SENT,
+    ADAPTER_MESSAGE_STATE_RECEIVED,
+    ADAPTER_MESSAGE_STATE_ERROR
+  } cec_adapter_message_state;
+
 
-  class CAdapterCommunication : CThread
+  class CCECAdapterMessage
   {
   public:
-    CAdapterCommunication(CLibCEC *controller);
+    CCECAdapterMessage(void) { clear(); }
+    CCECAdapterMessage(const cec_command &command);
+    CCECAdapterMessage &operator =(const CCECAdapterMessage &msg);
+    CStdString ToString(void) const;
+    CStdString MessageCodeAsString(void) const;
+
+    bool                    empty(void) const             { return packet.IsEmpty(); }
+    uint8_t                 operator[](uint8_t pos) const { return packet[pos]; }
+    uint8_t                 at(uint8_t pos) const         { return packet[pos]; }
+    uint8_t                 size(void) const              { return packet.size; }
+    void                    clear(void)                   { state = ADAPTER_MESSAGE_STATE_UNKNOWN; transmit_timeout = 0; packet.Clear(); maxTries = CEC_DEFAULT_TRANSMIT_RETRIES + 1; tries = 0; reply = MSGCODE_NOTHING; }
+    void                    shift(uint8_t iShiftBy)       { packet.Shift(iShiftBy); }
+    void                    push_back(uint8_t add)        { packet.PushBack(add); }
+    cec_adapter_messagecode message(void) const           { return packet.size >= 1 ? (cec_adapter_messagecode) (packet.At(0) & ~(MSGCODE_FRAME_EOM | MSGCODE_FRAME_ACK))  : MSGCODE_NOTHING; }
+    bool                    eom(void) const               { return packet.size >= 1 ? (packet.At(0) & MSGCODE_FRAME_EOM) != 0 : false; }
+    bool                    ack(void) const               { return packet.size >= 1 ? (packet.At(0) & MSGCODE_FRAME_ACK) != 0 : false; }
+    cec_logical_address     initiator(void) const         { return packet.size >= 2 ? (cec_logical_address) (packet.At(1) >> 4)  : CECDEVICE_UNKNOWN; };
+    cec_logical_address     destination(void) const       { return packet.size >= 2 ? (cec_logical_address) (packet.At(1) & 0xF) : CECDEVICE_UNKNOWN; };
+    bool                    is_error(void) const;
+    void                    push_escaped(uint8_t byte);
+    bool                    needs_retry(void) const       { return reply == MSGCODE_NOTHING ||
+                                                                   reply == MSGCODE_RECEIVE_FAILED ||
+                                                                   reply == MSGCODE_TIMEOUT_ERROR ||
+                                                                   reply == MSGCODE_TRANSMIT_FAILED_LINE ||
+                                                                   reply == MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA ||
+                                                                   reply == MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE ||
+                                                                   reply == MSGCODE_TRANSMIT_LINE_TIMEOUT; }
+
+    uint8_t                   maxTries;
+    uint8_t                   tries;
+    cec_adapter_messagecode   reply;
+    cec_datapacket            packet;
+    cec_adapter_message_state state;
+    int32_t                   transmit_timeout;
+    PLATFORM::CMutex          mutex;
+    PLATFORM::CCondition      condition;
+  };
+
+  class CCECProcessor;
+
+  class CAdapterCommunication : private PLATFORM::CThread
+  {
+  public:
+    CAdapterCommunication(CCECProcessor *processor);
     virtual ~CAdapterCommunication();
 
-    bool Open(const char *strPort, int iBaudRate = 38400, int iTimeoutMs = 10000);
-    bool Read(cec_frame &msg, int iTimeout = 1000);
-    bool Write(const cec_frame &frame);
+    bool Open(const char *strPort, uint16_t iBaudRate = 38400, uint32_t iTimeoutMs = 10000);
+    bool Read(CCECAdapterMessage &msg, uint32_t iTimeout = 1000);
+    bool Write(CCECAdapterMessage *data);
     bool PingAdapter(void);
     void Close(void);
-    bool IsOpen(void) const { return !m_bStop && m_bStarted; }
+    bool IsOpen(void);
     std::string GetError(void) const;
 
     void *Process(void);
 
+    bool SetLineTimeout(uint8_t iTimeout);
     bool StartBootloader(void);
-    bool SetAckMask(uint16_t iMask);
-    static void PushEscaped(cec_frame &vec, uint8_t byte);
+
   private:
-    void AddData(uint8_t *data, int iLen);
-    bool ReadFromDevice(int iTimeout);
+    void SendMessageToAdapter(CCECAdapterMessage *msg);
+    void WriteNextCommand(void);
+    void AddData(uint8_t *data, uint8_t iLen);
+    bool ReadFromDevice(uint32_t iTimeout);
 
-    CSerialPort *        m_port;
-    CLibCEC *            m_controller;
-    uint8_t*             m_inbuf;
-    int                  m_iInbufSize;
-    int                  m_iInbufUsed;
-    bool                 m_bStarted;
-    bool                 m_bStop;
-    CMutex               m_commMutex;
-    CMutex               m_bufferMutex;
-    CCondition           m_condition;
+    PLATFORM::CSerialPort *                      m_port;
+    CCECProcessor *                              m_processor;
+    PLATFORM::SyncedBuffer<uint8_t>              m_inBuffer;
+    PLATFORM::SyncedBuffer<CCECAdapterMessage *> m_outBuffer;
+    PLATFORM::CMutex                             m_mutex;
+    PLATFORM::CCondition                         m_rcvCondition;
+    PLATFORM::CCondition                         m_startCondition;
+    uint8_t                                      m_iLineTimeout;
   };
 };